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