1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include <unistd.h> /* for lseek prototype */ 18*7c478bd9Sstevel@tonic-gate #include "sh.h" 19*7c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 20*7c478bd9Sstevel@tonic-gate 21*7c478bd9Sstevel@tonic-gate /* 22*7c478bd9Sstevel@tonic-gate * C shell 23*7c478bd9Sstevel@tonic-gate */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate /* 26*7c478bd9Sstevel@tonic-gate * These routines perform variable substitution and quoting via ' and ". 27*7c478bd9Sstevel@tonic-gate * To this point these constructs have been preserved in the divided 28*7c478bd9Sstevel@tonic-gate * input words. Here we expand variables and turn quoting via ' and " into 29*7c478bd9Sstevel@tonic-gate * QUOTE bits on characters (which prevent further interpretation). 30*7c478bd9Sstevel@tonic-gate * If the `:q' modifier was applied during history expansion, then 31*7c478bd9Sstevel@tonic-gate * some QUOTEing may have occurred already, so we dont "trim()" here. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate int Dpeekc, Dpeekrd; /* Peeks for DgetC and Dreadc */ 35*7c478bd9Sstevel@tonic-gate tchar *Dcp, **Dvp; /* Input vector for Dreadc */ 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #define DEOF -1 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #define unDgetC(c) Dpeekc = c 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #define QUOTES (_Q|_Q1|_ESC) /* \ ' " ` */ 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate /* 44*7c478bd9Sstevel@tonic-gate * The following variables give the information about the current 45*7c478bd9Sstevel@tonic-gate * $ expansion, recording the current word position, the remaining 46*7c478bd9Sstevel@tonic-gate * words within this expansion, the count of remaining words, and the 47*7c478bd9Sstevel@tonic-gate * information about any : modifier which is being applied. 48*7c478bd9Sstevel@tonic-gate */ 49*7c478bd9Sstevel@tonic-gate tchar *dolp; /* Remaining chars from this word */ 50*7c478bd9Sstevel@tonic-gate tchar **dolnxt; /* Further words */ 51*7c478bd9Sstevel@tonic-gate int dolcnt; /* Count of further words */ 52*7c478bd9Sstevel@tonic-gate tchar dolmod; /* : modifier character */ 53*7c478bd9Sstevel@tonic-gate int dolmcnt; /* :gx -> 10000, else 1 */ 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* 56*7c478bd9Sstevel@tonic-gate * Fix up the $ expansions and quotations in the 57*7c478bd9Sstevel@tonic-gate * argument list to command t. 58*7c478bd9Sstevel@tonic-gate */ 59*7c478bd9Sstevel@tonic-gate Dfix(t) 60*7c478bd9Sstevel@tonic-gate register struct command *t; 61*7c478bd9Sstevel@tonic-gate { 62*7c478bd9Sstevel@tonic-gate register tchar **pp; 63*7c478bd9Sstevel@tonic-gate register tchar *p; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #ifdef TRACE 66*7c478bd9Sstevel@tonic-gate tprintf("TRACE- Dfix()\n"); 67*7c478bd9Sstevel@tonic-gate #endif 68*7c478bd9Sstevel@tonic-gate if (noexec) 69*7c478bd9Sstevel@tonic-gate return; 70*7c478bd9Sstevel@tonic-gate /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */ 71*7c478bd9Sstevel@tonic-gate for (pp = t->t_dcom; p = *pp++;) 72*7c478bd9Sstevel@tonic-gate while (*p) 73*7c478bd9Sstevel@tonic-gate if (cmap(*p++, _DOL|QUOTES)) { /* $, \, ', ", ` */ 74*7c478bd9Sstevel@tonic-gate Dfix2(t->t_dcom); /* found one */ 75*7c478bd9Sstevel@tonic-gate blkfree(t->t_dcom); 76*7c478bd9Sstevel@tonic-gate t->t_dcom = gargv; 77*7c478bd9Sstevel@tonic-gate gargv = 0; 78*7c478bd9Sstevel@tonic-gate return; 79*7c478bd9Sstevel@tonic-gate } 80*7c478bd9Sstevel@tonic-gate } 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate /* 83*7c478bd9Sstevel@tonic-gate * $ substitute one word, for i/o redirection 84*7c478bd9Sstevel@tonic-gate */ 85*7c478bd9Sstevel@tonic-gate tchar * 86*7c478bd9Sstevel@tonic-gate Dfix1(cp) 87*7c478bd9Sstevel@tonic-gate register tchar *cp; 88*7c478bd9Sstevel@tonic-gate { 89*7c478bd9Sstevel@tonic-gate tchar *Dv[2]; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate #ifdef TRACE 92*7c478bd9Sstevel@tonic-gate tprintf("TRACE- Dfix1()\n"); 93*7c478bd9Sstevel@tonic-gate #endif 94*7c478bd9Sstevel@tonic-gate if (noexec) 95*7c478bd9Sstevel@tonic-gate return (0); 96*7c478bd9Sstevel@tonic-gate Dv[0] = cp; Dv[1] = NOSTR; 97*7c478bd9Sstevel@tonic-gate Dfix2(Dv); 98*7c478bd9Sstevel@tonic-gate if (gargc != 1) { 99*7c478bd9Sstevel@tonic-gate setname(cp); 100*7c478bd9Sstevel@tonic-gate bferr("Ambiguous"); 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate cp = savestr(gargv[0]); 103*7c478bd9Sstevel@tonic-gate blkfree(gargv), gargv = 0; 104*7c478bd9Sstevel@tonic-gate return (cp); 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate /* 108*7c478bd9Sstevel@tonic-gate * Subroutine to do actual fixing after state initialization. 109*7c478bd9Sstevel@tonic-gate */ 110*7c478bd9Sstevel@tonic-gate Dfix2(v) 111*7c478bd9Sstevel@tonic-gate tchar **v; 112*7c478bd9Sstevel@tonic-gate { 113*7c478bd9Sstevel@tonic-gate tchar *agargv[GAVSIZ]; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate #ifdef TRACE 116*7c478bd9Sstevel@tonic-gate tprintf("TRACE- Dfix2()\n"); 117*7c478bd9Sstevel@tonic-gate #endif 118*7c478bd9Sstevel@tonic-gate ginit(agargv); /* Initialize glob's area pointers */ 119*7c478bd9Sstevel@tonic-gate Dvp = v; Dcp = S_ /* "" */;/* Setup input vector for Dreadc */ 120*7c478bd9Sstevel@tonic-gate unDgetC(0); unDredc(0); /* Clear out any old peeks (at error) */ 121*7c478bd9Sstevel@tonic-gate dolp = 0; dolcnt = 0; /* Clear out residual $ expands (...) */ 122*7c478bd9Sstevel@tonic-gate while (Dword()) 123*7c478bd9Sstevel@tonic-gate continue; 124*7c478bd9Sstevel@tonic-gate gargv = copyblk(gargv); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* 128*7c478bd9Sstevel@tonic-gate * Get a word. This routine is analogous to the routine 129*7c478bd9Sstevel@tonic-gate * word() in sh.lex.c for the main lexical input. One difference 130*7c478bd9Sstevel@tonic-gate * here is that we don't get a newline to terminate our expansion. 131*7c478bd9Sstevel@tonic-gate * Rather, DgetC will return a DEOF when we hit the end-of-input. 132*7c478bd9Sstevel@tonic-gate */ 133*7c478bd9Sstevel@tonic-gate Dword() 134*7c478bd9Sstevel@tonic-gate { 135*7c478bd9Sstevel@tonic-gate register int c, c1; 136*7c478bd9Sstevel@tonic-gate static tchar *wbuf = NULL; 137*7c478bd9Sstevel@tonic-gate static int wbufsiz = BUFSIZ; 138*7c478bd9Sstevel@tonic-gate register int wp = 0; 139*7c478bd9Sstevel@tonic-gate register bool dolflg; 140*7c478bd9Sstevel@tonic-gate bool sofar = 0; 141*7c478bd9Sstevel@tonic-gate #define DYNAMICBUFFER() \ 142*7c478bd9Sstevel@tonic-gate do { \ 143*7c478bd9Sstevel@tonic-gate if (wp >= wbufsiz) { \ 144*7c478bd9Sstevel@tonic-gate wbufsiz += BUFSIZ; \ 145*7c478bd9Sstevel@tonic-gate wbuf = xrealloc(wbuf, (wbufsiz+1) * sizeof (tchar)); \ 146*7c478bd9Sstevel@tonic-gate } \ 147*7c478bd9Sstevel@tonic-gate } while (0) 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate #ifdef TRACE 150*7c478bd9Sstevel@tonic-gate tprintf("TRACE- Dword()\n"); 151*7c478bd9Sstevel@tonic-gate #endif 152*7c478bd9Sstevel@tonic-gate if (wbuf == NULL) 153*7c478bd9Sstevel@tonic-gate wbuf = xalloc((wbufsiz+1) * sizeof (tchar)); 154*7c478bd9Sstevel@tonic-gate loop: 155*7c478bd9Sstevel@tonic-gate c = DgetC(DODOL); 156*7c478bd9Sstevel@tonic-gate switch (c) { 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate case DEOF: 159*7c478bd9Sstevel@tonic-gate deof: 160*7c478bd9Sstevel@tonic-gate if (sofar == 0) 161*7c478bd9Sstevel@tonic-gate return (0); 162*7c478bd9Sstevel@tonic-gate /* finish this word and catch the code above the next time */ 163*7c478bd9Sstevel@tonic-gate unDredc(c); 164*7c478bd9Sstevel@tonic-gate /* fall into ... */ 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate case '\n': 167*7c478bd9Sstevel@tonic-gate wbuf[wp] = 0; 168*7c478bd9Sstevel@tonic-gate goto ret; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate case ' ': 171*7c478bd9Sstevel@tonic-gate case '\t': 172*7c478bd9Sstevel@tonic-gate goto loop; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate case '`': 175*7c478bd9Sstevel@tonic-gate /* We preserve ` quotations which are done yet later */ 176*7c478bd9Sstevel@tonic-gate wbuf[wp++] = c; 177*7c478bd9Sstevel@tonic-gate case '\'': 178*7c478bd9Sstevel@tonic-gate case '"': 179*7c478bd9Sstevel@tonic-gate /* 180*7c478bd9Sstevel@tonic-gate * Note that DgetC never returns a QUOTES character 181*7c478bd9Sstevel@tonic-gate * from an expansion, so only true input quotes will 182*7c478bd9Sstevel@tonic-gate * get us here or out. 183*7c478bd9Sstevel@tonic-gate */ 184*7c478bd9Sstevel@tonic-gate c1 = c; 185*7c478bd9Sstevel@tonic-gate dolflg = c1 == '"' ? DODOL : 0; 186*7c478bd9Sstevel@tonic-gate for (;;) { 187*7c478bd9Sstevel@tonic-gate c = DgetC(dolflg); 188*7c478bd9Sstevel@tonic-gate if (c == c1) 189*7c478bd9Sstevel@tonic-gate break; 190*7c478bd9Sstevel@tonic-gate if (c == '\n' || c == DEOF) 191*7c478bd9Sstevel@tonic-gate error("Unmatched %c", (tchar) c1); 192*7c478bd9Sstevel@tonic-gate if ((c & (QUOTE|TRIM)) == ('\n' | QUOTE)) 193*7c478bd9Sstevel@tonic-gate --wp; 194*7c478bd9Sstevel@tonic-gate DYNAMICBUFFER(); 195*7c478bd9Sstevel@tonic-gate switch (c1) { 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate case '"': 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * Leave any `s alone for later. 200*7c478bd9Sstevel@tonic-gate * Other chars are all quoted, thus `...` 201*7c478bd9Sstevel@tonic-gate * can tell it was within "...". 202*7c478bd9Sstevel@tonic-gate */ 203*7c478bd9Sstevel@tonic-gate wbuf[wp++] = c == '`' ? '`' : c | QUOTE; 204*7c478bd9Sstevel@tonic-gate break; 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate case '\'': 207*7c478bd9Sstevel@tonic-gate /* Prevent all further interpretation */ 208*7c478bd9Sstevel@tonic-gate wbuf[wp++] = c | QUOTE; 209*7c478bd9Sstevel@tonic-gate break; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate case '`': 212*7c478bd9Sstevel@tonic-gate /* Leave all text alone for later */ 213*7c478bd9Sstevel@tonic-gate wbuf[wp++] = c; 214*7c478bd9Sstevel@tonic-gate break; 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate if (c1 == '`') { 218*7c478bd9Sstevel@tonic-gate DYNAMICBUFFER(); 219*7c478bd9Sstevel@tonic-gate wbuf[wp++] = '`'; 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate goto pack; /* continue the word */ 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate case '\\': 224*7c478bd9Sstevel@tonic-gate c = DgetC(0); /* No $ subst! */ 225*7c478bd9Sstevel@tonic-gate if (c == '\n' || c == DEOF) 226*7c478bd9Sstevel@tonic-gate goto loop; 227*7c478bd9Sstevel@tonic-gate c |= QUOTE; 228*7c478bd9Sstevel@tonic-gate break; 229*7c478bd9Sstevel@tonic-gate #ifdef MBCHAR /* Could be a space char from aux. codeset. */ 230*7c478bd9Sstevel@tonic-gate default: 231*7c478bd9Sstevel@tonic-gate if (isauxsp(c)) goto loop; 232*7c478bd9Sstevel@tonic-gate #endif /* MBCHAR */ 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate unDgetC(c); 235*7c478bd9Sstevel@tonic-gate pack: 236*7c478bd9Sstevel@tonic-gate sofar = 1; 237*7c478bd9Sstevel@tonic-gate /* pack up more characters in this word */ 238*7c478bd9Sstevel@tonic-gate for (;;) { 239*7c478bd9Sstevel@tonic-gate c = DgetC(DODOL); 240*7c478bd9Sstevel@tonic-gate if (c == '\\') { 241*7c478bd9Sstevel@tonic-gate c = DgetC(0); 242*7c478bd9Sstevel@tonic-gate if (c == DEOF) 243*7c478bd9Sstevel@tonic-gate goto deof; 244*7c478bd9Sstevel@tonic-gate if (c == '\n') 245*7c478bd9Sstevel@tonic-gate c = ' '; 246*7c478bd9Sstevel@tonic-gate else 247*7c478bd9Sstevel@tonic-gate c |= QUOTE; 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate if (c == DEOF) 250*7c478bd9Sstevel@tonic-gate goto deof; 251*7c478bd9Sstevel@tonic-gate if (cmap(c, _SP|_NL|_Q|_Q1) || 252*7c478bd9Sstevel@tonic-gate isauxsp(c)) { /* sp \t\n'"` or aux. sp */ 253*7c478bd9Sstevel@tonic-gate unDgetC(c); 254*7c478bd9Sstevel@tonic-gate if (cmap(c, QUOTES)) 255*7c478bd9Sstevel@tonic-gate goto loop; 256*7c478bd9Sstevel@tonic-gate DYNAMICBUFFER(); 257*7c478bd9Sstevel@tonic-gate wbuf[wp++] = 0; 258*7c478bd9Sstevel@tonic-gate goto ret; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate DYNAMICBUFFER(); 261*7c478bd9Sstevel@tonic-gate wbuf[wp++] = c; 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate ret: 264*7c478bd9Sstevel@tonic-gate Gcat(S_ /* "" */, wbuf); 265*7c478bd9Sstevel@tonic-gate return (1); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* 269*7c478bd9Sstevel@tonic-gate * Get a character, performing $ substitution unless flag is 0. 270*7c478bd9Sstevel@tonic-gate * Any QUOTES character which is returned from a $ expansion is 271*7c478bd9Sstevel@tonic-gate * QUOTEd so that it will not be recognized above. 272*7c478bd9Sstevel@tonic-gate */ 273*7c478bd9Sstevel@tonic-gate DgetC(flag) 274*7c478bd9Sstevel@tonic-gate register int flag; 275*7c478bd9Sstevel@tonic-gate { 276*7c478bd9Sstevel@tonic-gate register int c; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate top: 279*7c478bd9Sstevel@tonic-gate if (c = Dpeekc) { 280*7c478bd9Sstevel@tonic-gate Dpeekc = 0; 281*7c478bd9Sstevel@tonic-gate return (c); 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate if (lap) { 284*7c478bd9Sstevel@tonic-gate c = *lap++ & (QUOTE|TRIM); 285*7c478bd9Sstevel@tonic-gate if (c == 0) { 286*7c478bd9Sstevel@tonic-gate lap = 0; 287*7c478bd9Sstevel@tonic-gate goto top; 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate quotspec: 290*7c478bd9Sstevel@tonic-gate /* 291*7c478bd9Sstevel@tonic-gate * don't quote things if there was an error (err!=0) 292*7c478bd9Sstevel@tonic-gate * the input is original, not from a substitution and 293*7c478bd9Sstevel@tonic-gate * therefore should not be quoted 294*7c478bd9Sstevel@tonic-gate */ 295*7c478bd9Sstevel@tonic-gate if (!err && cmap(c, QUOTES)) 296*7c478bd9Sstevel@tonic-gate return (c | QUOTE); 297*7c478bd9Sstevel@tonic-gate return (c); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate if (dolp) { 300*7c478bd9Sstevel@tonic-gate if (c = *dolp++ & (QUOTE|TRIM)) 301*7c478bd9Sstevel@tonic-gate goto quotspec; 302*7c478bd9Sstevel@tonic-gate if (dolcnt > 0) { 303*7c478bd9Sstevel@tonic-gate setDolp(*dolnxt++); 304*7c478bd9Sstevel@tonic-gate --dolcnt; 305*7c478bd9Sstevel@tonic-gate return (' '); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate dolp = 0; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate if (dolcnt > 0) { 310*7c478bd9Sstevel@tonic-gate setDolp(*dolnxt++); 311*7c478bd9Sstevel@tonic-gate --dolcnt; 312*7c478bd9Sstevel@tonic-gate goto top; 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate c = Dredc(); 315*7c478bd9Sstevel@tonic-gate if (c == '$' && flag) { 316*7c478bd9Sstevel@tonic-gate Dgetdol(); 317*7c478bd9Sstevel@tonic-gate goto top; 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate return (c); 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate tchar *nulvec[] = { 0 }; 323*7c478bd9Sstevel@tonic-gate struct varent nulargv = { nulvec, S_argv, 0 }; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* 326*7c478bd9Sstevel@tonic-gate * Handle the multitudinous $ expansion forms. 327*7c478bd9Sstevel@tonic-gate * Ugh. 328*7c478bd9Sstevel@tonic-gate */ 329*7c478bd9Sstevel@tonic-gate Dgetdol() 330*7c478bd9Sstevel@tonic-gate { 331*7c478bd9Sstevel@tonic-gate register tchar *np; 332*7c478bd9Sstevel@tonic-gate register struct varent *vp; 333*7c478bd9Sstevel@tonic-gate tchar name[MAX_VREF_LEN]; 334*7c478bd9Sstevel@tonic-gate int c, sc; 335*7c478bd9Sstevel@tonic-gate int subscr = 0, lwb = 1, upb = 0; 336*7c478bd9Sstevel@tonic-gate bool dimen = 0, bitset = 0; 337*7c478bd9Sstevel@tonic-gate tchar wbuf[BUFSIZ]; 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate #ifdef TRACE 340*7c478bd9Sstevel@tonic-gate tprintf("TRACE- Dgetdol()\n"); 341*7c478bd9Sstevel@tonic-gate #endif 342*7c478bd9Sstevel@tonic-gate dolmod = dolmcnt = 0; 343*7c478bd9Sstevel@tonic-gate c = sc = DgetC(0); 344*7c478bd9Sstevel@tonic-gate if (c == '{') 345*7c478bd9Sstevel@tonic-gate c = DgetC(0); /* sc is { to take } later */ 346*7c478bd9Sstevel@tonic-gate if ((c & TRIM) == '#') 347*7c478bd9Sstevel@tonic-gate dimen++, c = DgetC(0); /* $# takes dimension */ 348*7c478bd9Sstevel@tonic-gate else if (c == '?') 349*7c478bd9Sstevel@tonic-gate bitset++, c = DgetC(0); /* $? tests existence */ 350*7c478bd9Sstevel@tonic-gate switch (c) { 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate case '$': 353*7c478bd9Sstevel@tonic-gate if (dimen || bitset) 354*7c478bd9Sstevel@tonic-gate syntax: 355*7c478bd9Sstevel@tonic-gate error("Variable syntax"); /* No $?$, $#$ */ 356*7c478bd9Sstevel@tonic-gate setDolp(doldol); 357*7c478bd9Sstevel@tonic-gate goto eatbrac; 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate case '<'|QUOTE: 360*7c478bd9Sstevel@tonic-gate if (dimen || bitset) 361*7c478bd9Sstevel@tonic-gate goto syntax; /* No $?<, $#< */ 362*7c478bd9Sstevel@tonic-gate for (np = wbuf; read_(OLDSTD, np, 1) == 1; np++) { 363*7c478bd9Sstevel@tonic-gate if (np >= &wbuf[BUFSIZ-1]) 364*7c478bd9Sstevel@tonic-gate error("$< line too long"); 365*7c478bd9Sstevel@tonic-gate if (*np <= 0 || *np == '\n') 366*7c478bd9Sstevel@tonic-gate break; 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate *np = 0; 369*7c478bd9Sstevel@tonic-gate /* 370*7c478bd9Sstevel@tonic-gate * KLUDGE: dolmod is set here because it will 371*7c478bd9Sstevel@tonic-gate * cause setDolp to call domod and thus to copy wbuf. 372*7c478bd9Sstevel@tonic-gate * Otherwise setDolp would use it directly. If we saved 373*7c478bd9Sstevel@tonic-gate * it ourselves, no one would know when to free it. 374*7c478bd9Sstevel@tonic-gate * The actual function of the 'q' causes filename 375*7c478bd9Sstevel@tonic-gate * expansion not to be done on the interpolated value. 376*7c478bd9Sstevel@tonic-gate */ 377*7c478bd9Sstevel@tonic-gate dolmod = 'q'; 378*7c478bd9Sstevel@tonic-gate dolmcnt = 10000; 379*7c478bd9Sstevel@tonic-gate setDolp(wbuf); 380*7c478bd9Sstevel@tonic-gate goto eatbrac; 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate case DEOF: 383*7c478bd9Sstevel@tonic-gate case '\n': 384*7c478bd9Sstevel@tonic-gate goto syntax; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate case '*': 387*7c478bd9Sstevel@tonic-gate (void) strcpy_(name, S_argv); 388*7c478bd9Sstevel@tonic-gate vp = adrof(S_argv); 389*7c478bd9Sstevel@tonic-gate subscr = -1; /* Prevent eating [...] */ 390*7c478bd9Sstevel@tonic-gate break; 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate default: 393*7c478bd9Sstevel@tonic-gate np = name; 394*7c478bd9Sstevel@tonic-gate if (digit(c)) { 395*7c478bd9Sstevel@tonic-gate if (dimen) 396*7c478bd9Sstevel@tonic-gate goto syntax; /* No $#1, e.g. */ 397*7c478bd9Sstevel@tonic-gate subscr = 0; 398*7c478bd9Sstevel@tonic-gate do { 399*7c478bd9Sstevel@tonic-gate subscr = subscr * 10 + c - '0'; 400*7c478bd9Sstevel@tonic-gate c = DgetC(0); 401*7c478bd9Sstevel@tonic-gate } while (digit(c)); 402*7c478bd9Sstevel@tonic-gate unDredc(c); 403*7c478bd9Sstevel@tonic-gate if (subscr < 0) 404*7c478bd9Sstevel@tonic-gate error("Subscript out of range"); 405*7c478bd9Sstevel@tonic-gate if (subscr == 0) { 406*7c478bd9Sstevel@tonic-gate if (bitset) { 407*7c478bd9Sstevel@tonic-gate dolp = file ? S_1/*"1"*/ : S_0/*"0"*/; 408*7c478bd9Sstevel@tonic-gate goto eatbrac; 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate if (file == 0) 411*7c478bd9Sstevel@tonic-gate error("No file for $0"); 412*7c478bd9Sstevel@tonic-gate setDolp(file); 413*7c478bd9Sstevel@tonic-gate goto eatbrac; 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate if (bitset) 416*7c478bd9Sstevel@tonic-gate goto syntax; 417*7c478bd9Sstevel@tonic-gate vp = adrof(S_argv); 418*7c478bd9Sstevel@tonic-gate if (vp == 0) { 419*7c478bd9Sstevel@tonic-gate vp = &nulargv; 420*7c478bd9Sstevel@tonic-gate goto eatmod; 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate break; 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate if (!alnum(c)) 425*7c478bd9Sstevel@tonic-gate goto syntax; 426*7c478bd9Sstevel@tonic-gate for (;;) { 427*7c478bd9Sstevel@tonic-gate *np++ = c; 428*7c478bd9Sstevel@tonic-gate c = DgetC(0); 429*7c478bd9Sstevel@tonic-gate if (!alnum(c)) 430*7c478bd9Sstevel@tonic-gate break; 431*7c478bd9Sstevel@tonic-gate /* if variable name is > 20, complain */ 432*7c478bd9Sstevel@tonic-gate if (np >= &name[MAX_VAR_LEN]) 433*7c478bd9Sstevel@tonic-gate error("Variable name too long"); 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate *np++ = 0; 437*7c478bd9Sstevel@tonic-gate unDredc(c); 438*7c478bd9Sstevel@tonic-gate vp = adrof(name); 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate if (bitset) { 441*7c478bd9Sstevel@tonic-gate /* getenv() to getenv_(), because 'name''s type is now tchar * */ 442*7c478bd9Sstevel@tonic-gate /* no need to xalloc */ 443*7c478bd9Sstevel@tonic-gate dolp = (vp || getenv_(name)) ? S_1 /*"1"*/ : S_0/*"0"*/; 444*7c478bd9Sstevel@tonic-gate goto eatbrac; 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate if (vp == 0) { 447*7c478bd9Sstevel@tonic-gate /* getenv() to getenv_(), because 'name''s type is now tchar * */ 448*7c478bd9Sstevel@tonic-gate /* no need to xalloc */ 449*7c478bd9Sstevel@tonic-gate np = getenv_(name); 450*7c478bd9Sstevel@tonic-gate if (np) { 451*7c478bd9Sstevel@tonic-gate addla(np); 452*7c478bd9Sstevel@tonic-gate goto eatbrac; 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate udvar(name); 455*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate c = DgetC(0); 458*7c478bd9Sstevel@tonic-gate upb = blklen(vp->vec); 459*7c478bd9Sstevel@tonic-gate if (dimen == 0 && subscr == 0 && c == '[') { 460*7c478bd9Sstevel@tonic-gate np = name; 461*7c478bd9Sstevel@tonic-gate for (;;) { 462*7c478bd9Sstevel@tonic-gate c = DgetC(DODOL); /* Allow $ expand within [ ] */ 463*7c478bd9Sstevel@tonic-gate if (c == ']') 464*7c478bd9Sstevel@tonic-gate break; 465*7c478bd9Sstevel@tonic-gate if (c == '\n' || c == DEOF) 466*7c478bd9Sstevel@tonic-gate goto syntax; 467*7c478bd9Sstevel@tonic-gate if (np >= &name[MAX_VREF_LEN]) 468*7c478bd9Sstevel@tonic-gate error("Variable reference too long"); 469*7c478bd9Sstevel@tonic-gate *np++ = c; 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate *np = 0, np = name; 472*7c478bd9Sstevel@tonic-gate if (dolp || dolcnt) /* $ exp must end before ] */ 473*7c478bd9Sstevel@tonic-gate goto syntax; 474*7c478bd9Sstevel@tonic-gate if (!*np) 475*7c478bd9Sstevel@tonic-gate goto syntax; 476*7c478bd9Sstevel@tonic-gate if (digit(*np)) { 477*7c478bd9Sstevel@tonic-gate register int i = 0; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate while (digit(*np)) 480*7c478bd9Sstevel@tonic-gate i = i * 10 + *np++ - '0'; 481*7c478bd9Sstevel@tonic-gate /* if ((i < 0 || i > upb) && !any(*np, "-*")) {*/ 482*7c478bd9Sstevel@tonic-gate if ((i < 0 || i > upb) && (*np!='-') && (*np!='*')) { 483*7c478bd9Sstevel@tonic-gate oob: 484*7c478bd9Sstevel@tonic-gate setname(vp->v_name); 485*7c478bd9Sstevel@tonic-gate error("Subscript out of range"); 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate lwb = i; 488*7c478bd9Sstevel@tonic-gate if (!*np) 489*7c478bd9Sstevel@tonic-gate upb = lwb, np = S_AST/*"*"*/; 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate if (*np == '*') 492*7c478bd9Sstevel@tonic-gate np++; 493*7c478bd9Sstevel@tonic-gate else if (*np != '-') 494*7c478bd9Sstevel@tonic-gate goto syntax; 495*7c478bd9Sstevel@tonic-gate else { 496*7c478bd9Sstevel@tonic-gate register int i = upb; 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate np++; 499*7c478bd9Sstevel@tonic-gate if (digit(*np)) { 500*7c478bd9Sstevel@tonic-gate i = 0; 501*7c478bd9Sstevel@tonic-gate while (digit(*np)) 502*7c478bd9Sstevel@tonic-gate i = i * 10 + *np++ - '0'; 503*7c478bd9Sstevel@tonic-gate if (i < 0 || i > upb) 504*7c478bd9Sstevel@tonic-gate goto oob; 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate if (i < lwb) 507*7c478bd9Sstevel@tonic-gate upb = lwb - 1; 508*7c478bd9Sstevel@tonic-gate else 509*7c478bd9Sstevel@tonic-gate upb = i; 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate if (lwb == 0) { 512*7c478bd9Sstevel@tonic-gate if (upb != 0) 513*7c478bd9Sstevel@tonic-gate goto oob; 514*7c478bd9Sstevel@tonic-gate upb = -1; 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate if (*np) 517*7c478bd9Sstevel@tonic-gate goto syntax; 518*7c478bd9Sstevel@tonic-gate } else { 519*7c478bd9Sstevel@tonic-gate if (subscr > 0) 520*7c478bd9Sstevel@tonic-gate if (subscr > upb) 521*7c478bd9Sstevel@tonic-gate lwb = 1, upb = 0; 522*7c478bd9Sstevel@tonic-gate else 523*7c478bd9Sstevel@tonic-gate lwb = upb = subscr; 524*7c478bd9Sstevel@tonic-gate unDredc(c); 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate if (dimen) { 527*7c478bd9Sstevel@tonic-gate tchar *cp = putn(upb - lwb + 1); 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate addla(cp); 530*7c478bd9Sstevel@tonic-gate xfree(cp); 531*7c478bd9Sstevel@tonic-gate } else { 532*7c478bd9Sstevel@tonic-gate eatmod: 533*7c478bd9Sstevel@tonic-gate c = DgetC(0); 534*7c478bd9Sstevel@tonic-gate if (c == ':') { 535*7c478bd9Sstevel@tonic-gate c = DgetC(0), dolmcnt = 1; 536*7c478bd9Sstevel@tonic-gate if (c == 'g') 537*7c478bd9Sstevel@tonic-gate c = DgetC(0), dolmcnt = 10000; 538*7c478bd9Sstevel@tonic-gate if (!any(c, S_htrqxe)) 539*7c478bd9Sstevel@tonic-gate error("Bad : mod in $"); 540*7c478bd9Sstevel@tonic-gate dolmod = c; 541*7c478bd9Sstevel@tonic-gate if (c == 'q') 542*7c478bd9Sstevel@tonic-gate dolmcnt = 10000; 543*7c478bd9Sstevel@tonic-gate } else 544*7c478bd9Sstevel@tonic-gate unDredc(c); 545*7c478bd9Sstevel@tonic-gate dolnxt = &vp->vec[lwb - 1]; 546*7c478bd9Sstevel@tonic-gate dolcnt = upb - lwb + 1; 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate eatbrac: 549*7c478bd9Sstevel@tonic-gate if (sc == '{') { 550*7c478bd9Sstevel@tonic-gate c = Dredc(); 551*7c478bd9Sstevel@tonic-gate if (c != '}') 552*7c478bd9Sstevel@tonic-gate goto syntax; 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate setDolp(cp) 557*7c478bd9Sstevel@tonic-gate register tchar *cp; 558*7c478bd9Sstevel@tonic-gate { 559*7c478bd9Sstevel@tonic-gate register tchar *dp; 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate #ifdef TRACE 562*7c478bd9Sstevel@tonic-gate tprintf("TRACE- setDolp()\n"); 563*7c478bd9Sstevel@tonic-gate #endif 564*7c478bd9Sstevel@tonic-gate if (dolmod == 0 || dolmcnt == 0) { 565*7c478bd9Sstevel@tonic-gate dolp = cp; 566*7c478bd9Sstevel@tonic-gate return; 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate dp = domod(cp, dolmod); 569*7c478bd9Sstevel@tonic-gate if (dp) { 570*7c478bd9Sstevel@tonic-gate dolmcnt--; 571*7c478bd9Sstevel@tonic-gate addla(dp); 572*7c478bd9Sstevel@tonic-gate xfree(dp); 573*7c478bd9Sstevel@tonic-gate } else 574*7c478bd9Sstevel@tonic-gate addla(cp); 575*7c478bd9Sstevel@tonic-gate dolp = S_/*""*/; 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate unDredc(c) 579*7c478bd9Sstevel@tonic-gate int c; 580*7c478bd9Sstevel@tonic-gate { 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate Dpeekrd = c; 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate Dredc() 586*7c478bd9Sstevel@tonic-gate { 587*7c478bd9Sstevel@tonic-gate register int c; 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate if (c = Dpeekrd) { 590*7c478bd9Sstevel@tonic-gate Dpeekrd = 0; 591*7c478bd9Sstevel@tonic-gate return (c); 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate if (Dcp && (c = *Dcp++)) 594*7c478bd9Sstevel@tonic-gate return (c&(QUOTE|TRIM)); 595*7c478bd9Sstevel@tonic-gate if (*Dvp == 0) { 596*7c478bd9Sstevel@tonic-gate Dcp = 0; 597*7c478bd9Sstevel@tonic-gate return (DEOF); 598*7c478bd9Sstevel@tonic-gate } 599*7c478bd9Sstevel@tonic-gate Dcp = *Dvp++; 600*7c478bd9Sstevel@tonic-gate return (' '); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate Dtestq(c) 604*7c478bd9Sstevel@tonic-gate register int c; 605*7c478bd9Sstevel@tonic-gate { 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate if (cmap(c, QUOTES)) 608*7c478bd9Sstevel@tonic-gate gflag = 1; 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate /* 612*7c478bd9Sstevel@tonic-gate * Form a shell temporary file (in unit 0) from the words 613*7c478bd9Sstevel@tonic-gate * of the shell input up to a line the same as "term". 614*7c478bd9Sstevel@tonic-gate * Unit 0 should have been closed before this call. 615*7c478bd9Sstevel@tonic-gate */ 616*7c478bd9Sstevel@tonic-gate heredoc(term) 617*7c478bd9Sstevel@tonic-gate tchar *term; 618*7c478bd9Sstevel@tonic-gate { 619*7c478bd9Sstevel@tonic-gate register int c; 620*7c478bd9Sstevel@tonic-gate tchar *Dv[2]; 621*7c478bd9Sstevel@tonic-gate tchar obuf[BUFSIZ], lbuf[BUFSIZ], mbuf[BUFSIZ]; 622*7c478bd9Sstevel@tonic-gate int ocnt, lcnt, mcnt; 623*7c478bd9Sstevel@tonic-gate register tchar *lbp, *obp, *mbp; 624*7c478bd9Sstevel@tonic-gate tchar **vp; 625*7c478bd9Sstevel@tonic-gate bool quoted; 626*7c478bd9Sstevel@tonic-gate tchar shtemp[] = {'/', 't', 'm', 'p', '/', 's', 'h', 'X', 'X', 'X', 627*7c478bd9Sstevel@tonic-gate 'X', 'X', 'X', 0}; 628*7c478bd9Sstevel@tonic-gate int fd1; 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate #ifdef TRACE 631*7c478bd9Sstevel@tonic-gate tprintf("TRACE- heredoc()\n"); 632*7c478bd9Sstevel@tonic-gate #endif 633*7c478bd9Sstevel@tonic-gate if ((fd1 = mkstemp_(shtemp)) < 0) 634*7c478bd9Sstevel@tonic-gate Perror(shtemp); 635*7c478bd9Sstevel@tonic-gate (void) unlink_(shtemp); /* 0 0 inode! */ 636*7c478bd9Sstevel@tonic-gate unsetfd(fd1); 637*7c478bd9Sstevel@tonic-gate Dv[0] = term; Dv[1] = NOSTR; gflag = 0; 638*7c478bd9Sstevel@tonic-gate trim(Dv); rscan(Dv, Dtestq); quoted = gflag; 639*7c478bd9Sstevel@tonic-gate ocnt = BUFSIZ; obp = obuf; 640*7c478bd9Sstevel@tonic-gate for (;;) { 641*7c478bd9Sstevel@tonic-gate /* 642*7c478bd9Sstevel@tonic-gate * Read up a line 643*7c478bd9Sstevel@tonic-gate */ 644*7c478bd9Sstevel@tonic-gate lbp = lbuf; lcnt = BUFSIZ - 4; 645*7c478bd9Sstevel@tonic-gate for (;;) { 646*7c478bd9Sstevel@tonic-gate c = readc(1); /* 1 -> Want EOF returns */ 647*7c478bd9Sstevel@tonic-gate if (c < 0) { 648*7c478bd9Sstevel@tonic-gate setname(term); 649*7c478bd9Sstevel@tonic-gate bferr("<< terminator not found"); 650*7c478bd9Sstevel@tonic-gate } 651*7c478bd9Sstevel@tonic-gate if (c == '\n') 652*7c478bd9Sstevel@tonic-gate break; 653*7c478bd9Sstevel@tonic-gate if (c &= TRIM) { 654*7c478bd9Sstevel@tonic-gate *lbp++ = c; 655*7c478bd9Sstevel@tonic-gate if (--lcnt < 0) { 656*7c478bd9Sstevel@tonic-gate setname(S_LESLES/*"<<"*/); 657*7c478bd9Sstevel@tonic-gate error("Line overflow"); 658*7c478bd9Sstevel@tonic-gate } 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate *lbp = 0; 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* 664*7c478bd9Sstevel@tonic-gate * Compare to terminator -- before expansion 665*7c478bd9Sstevel@tonic-gate */ 666*7c478bd9Sstevel@tonic-gate if (eq(lbuf, term)) { 667*7c478bd9Sstevel@tonic-gate (void) write_(0, obuf, BUFSIZ - ocnt); 668*7c478bd9Sstevel@tonic-gate (void) lseek(0, (off_t)0, 0); 669*7c478bd9Sstevel@tonic-gate return; 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate /* 673*7c478bd9Sstevel@tonic-gate * If term was quoted or -n just pass it on 674*7c478bd9Sstevel@tonic-gate */ 675*7c478bd9Sstevel@tonic-gate if (quoted || noexec) { 676*7c478bd9Sstevel@tonic-gate *lbp++ = '\n'; *lbp = 0; 677*7c478bd9Sstevel@tonic-gate for (lbp = lbuf; c = *lbp++;) { 678*7c478bd9Sstevel@tonic-gate *obp++ = c; 679*7c478bd9Sstevel@tonic-gate if (--ocnt == 0) { 680*7c478bd9Sstevel@tonic-gate (void) write_(0, obuf, BUFSIZ); 681*7c478bd9Sstevel@tonic-gate obp = obuf; ocnt = BUFSIZ; 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate } 684*7c478bd9Sstevel@tonic-gate continue; 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate /* 688*7c478bd9Sstevel@tonic-gate * Term wasn't quoted so variable and then command 689*7c478bd9Sstevel@tonic-gate * expand the input line 690*7c478bd9Sstevel@tonic-gate */ 691*7c478bd9Sstevel@tonic-gate Dcp = lbuf; Dvp = Dv + 1; mbp = mbuf; mcnt = BUFSIZ - 4; 692*7c478bd9Sstevel@tonic-gate for (;;) { 693*7c478bd9Sstevel@tonic-gate c = DgetC(DODOL); 694*7c478bd9Sstevel@tonic-gate if (c == DEOF) 695*7c478bd9Sstevel@tonic-gate break; 696*7c478bd9Sstevel@tonic-gate if ((c &= TRIM) == 0) 697*7c478bd9Sstevel@tonic-gate continue; 698*7c478bd9Sstevel@tonic-gate /* \ quotes \ $ ` here */ 699*7c478bd9Sstevel@tonic-gate if (c =='\\') { 700*7c478bd9Sstevel@tonic-gate c = DgetC(0); 701*7c478bd9Sstevel@tonic-gate /* if (!any(c, "$\\`"))*/ 702*7c478bd9Sstevel@tonic-gate if ((c!='$')&&(c!='\\')&&(c!='`')) 703*7c478bd9Sstevel@tonic-gate unDgetC(c | QUOTE), c = '\\'; 704*7c478bd9Sstevel@tonic-gate else 705*7c478bd9Sstevel@tonic-gate c |= QUOTE; 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate *mbp++ = c; 708*7c478bd9Sstevel@tonic-gate if (--mcnt == 0) { 709*7c478bd9Sstevel@tonic-gate setname(S_LESLES/*"<<"*/); 710*7c478bd9Sstevel@tonic-gate bferr("Line overflow"); 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate } 713*7c478bd9Sstevel@tonic-gate *mbp++ = 0; 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate /* 716*7c478bd9Sstevel@tonic-gate * If any ` in line do command substitution 717*7c478bd9Sstevel@tonic-gate */ 718*7c478bd9Sstevel@tonic-gate mbp = mbuf; 719*7c478bd9Sstevel@tonic-gate if (any('`', mbp)) { 720*7c478bd9Sstevel@tonic-gate /* 721*7c478bd9Sstevel@tonic-gate * 1 arg to dobackp causes substitution to be literal. 722*7c478bd9Sstevel@tonic-gate * Words are broken only at newlines so that all blanks 723*7c478bd9Sstevel@tonic-gate * and tabs are preserved. Blank lines (null words) 724*7c478bd9Sstevel@tonic-gate * are not discarded. 725*7c478bd9Sstevel@tonic-gate */ 726*7c478bd9Sstevel@tonic-gate vp = dobackp(mbuf, 1); 727*7c478bd9Sstevel@tonic-gate } else 728*7c478bd9Sstevel@tonic-gate /* Setup trivial vector similar to return of dobackp */ 729*7c478bd9Sstevel@tonic-gate Dv[0] = mbp, Dv[1] = NOSTR, vp = Dv; 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate /* 732*7c478bd9Sstevel@tonic-gate * Resurrect the words from the command substitution 733*7c478bd9Sstevel@tonic-gate * each separated by a newline. Note that the last 734*7c478bd9Sstevel@tonic-gate * newline of a command substitution will have been 735*7c478bd9Sstevel@tonic-gate * discarded, but we put a newline after the last word 736*7c478bd9Sstevel@tonic-gate * because this represents the newline after the last 737*7c478bd9Sstevel@tonic-gate * input line! 738*7c478bd9Sstevel@tonic-gate */ 739*7c478bd9Sstevel@tonic-gate for (; *vp; vp++) { 740*7c478bd9Sstevel@tonic-gate for (mbp = *vp; *mbp; mbp++) { 741*7c478bd9Sstevel@tonic-gate *obp++ = *mbp & TRIM; 742*7c478bd9Sstevel@tonic-gate if (--ocnt == 0) { 743*7c478bd9Sstevel@tonic-gate (void) write_(0, obuf, BUFSIZ); 744*7c478bd9Sstevel@tonic-gate obp = obuf; ocnt = BUFSIZ; 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate *obp++ = '\n'; 748*7c478bd9Sstevel@tonic-gate if (--ocnt == 0) { 749*7c478bd9Sstevel@tonic-gate (void) write_(0, obuf, BUFSIZ); 750*7c478bd9Sstevel@tonic-gate obp = obuf; ocnt = BUFSIZ; 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate if (pargv) 754*7c478bd9Sstevel@tonic-gate blkfree(pargv), pargv = 0; 755*7c478bd9Sstevel@tonic-gate } 756*7c478bd9Sstevel@tonic-gate } 757