17c478bd9Sstevel@tonic-gate /* 26c02b4a4Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate #include <unistd.h> /* for lseek prototype */ 187c478bd9Sstevel@tonic-gate #include "sh.h" 197c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 207c478bd9Sstevel@tonic-gate 217c478bd9Sstevel@tonic-gate /* 227c478bd9Sstevel@tonic-gate * C shell 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate /* 267c478bd9Sstevel@tonic-gate * These routines perform variable substitution and quoting via ' and ". 277c478bd9Sstevel@tonic-gate * To this point these constructs have been preserved in the divided 287c478bd9Sstevel@tonic-gate * input words. Here we expand variables and turn quoting via ' and " into 297c478bd9Sstevel@tonic-gate * QUOTE bits on characters (which prevent further interpretation). 307c478bd9Sstevel@tonic-gate * If the `:q' modifier was applied during history expansion, then 317c478bd9Sstevel@tonic-gate * some QUOTEing may have occurred already, so we dont "trim()" here. 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate int Dpeekc, Dpeekrd; /* Peeks for DgetC and Dreadc */ 357c478bd9Sstevel@tonic-gate tchar *Dcp, **Dvp; /* Input vector for Dreadc */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #define DEOF -1 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #define unDgetC(c) Dpeekc = c 407c478bd9Sstevel@tonic-gate 41*65b0c20eSnakanon #define QUOTES (_Q|_Q1|_ESC) /* \ ' " ` */ 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* 447c478bd9Sstevel@tonic-gate * The following variables give the information about the current 457c478bd9Sstevel@tonic-gate * $ expansion, recording the current word position, the remaining 467c478bd9Sstevel@tonic-gate * words within this expansion, the count of remaining words, and the 477c478bd9Sstevel@tonic-gate * information about any : modifier which is being applied. 487c478bd9Sstevel@tonic-gate */ 497c478bd9Sstevel@tonic-gate tchar *dolp; /* Remaining chars from this word */ 507c478bd9Sstevel@tonic-gate tchar **dolnxt; /* Further words */ 517c478bd9Sstevel@tonic-gate int dolcnt; /* Count of further words */ 527c478bd9Sstevel@tonic-gate tchar dolmod; /* : modifier character */ 537c478bd9Sstevel@tonic-gate int dolmcnt; /* :gx -> 10000, else 1 */ 547c478bd9Sstevel@tonic-gate 556c02b4a4Smuffin void Dfix2(tchar **); 566c02b4a4Smuffin void Dgetdol(void); 576c02b4a4Smuffin void setDolp(tchar *); 586c02b4a4Smuffin void unDredc(int); 596c02b4a4Smuffin 607c478bd9Sstevel@tonic-gate /* 617c478bd9Sstevel@tonic-gate * Fix up the $ expansions and quotations in the 627c478bd9Sstevel@tonic-gate * argument list to command t. 637c478bd9Sstevel@tonic-gate */ 646c02b4a4Smuffin void 656c02b4a4Smuffin Dfix(struct command *t) 667c478bd9Sstevel@tonic-gate { 676c02b4a4Smuffin tchar **pp; 686c02b4a4Smuffin tchar *p; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #ifdef TRACE 717c478bd9Sstevel@tonic-gate tprintf("TRACE- Dfix()\n"); 727c478bd9Sstevel@tonic-gate #endif 737c478bd9Sstevel@tonic-gate if (noexec) 747c478bd9Sstevel@tonic-gate return; 757c478bd9Sstevel@tonic-gate /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */ 76*65b0c20eSnakanon for (pp = t->t_dcom; p = *pp++; ) 777c478bd9Sstevel@tonic-gate while (*p) 787c478bd9Sstevel@tonic-gate if (cmap(*p++, _DOL|QUOTES)) { /* $, \, ', ", ` */ 797c478bd9Sstevel@tonic-gate Dfix2(t->t_dcom); /* found one */ 807c478bd9Sstevel@tonic-gate blkfree(t->t_dcom); 817c478bd9Sstevel@tonic-gate t->t_dcom = gargv; 827c478bd9Sstevel@tonic-gate gargv = 0; 837c478bd9Sstevel@tonic-gate return; 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * $ substitute one word, for i/o redirection 897c478bd9Sstevel@tonic-gate */ 907c478bd9Sstevel@tonic-gate tchar * 916c02b4a4Smuffin Dfix1(tchar *cp) 927c478bd9Sstevel@tonic-gate { 937c478bd9Sstevel@tonic-gate tchar *Dv[2]; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate #ifdef TRACE 967c478bd9Sstevel@tonic-gate tprintf("TRACE- Dfix1()\n"); 977c478bd9Sstevel@tonic-gate #endif 987c478bd9Sstevel@tonic-gate if (noexec) 997c478bd9Sstevel@tonic-gate return (0); 1007c478bd9Sstevel@tonic-gate Dv[0] = cp; Dv[1] = NOSTR; 1017c478bd9Sstevel@tonic-gate Dfix2(Dv); 1027c478bd9Sstevel@tonic-gate if (gargc != 1) { 1037c478bd9Sstevel@tonic-gate setname(cp); 1047c478bd9Sstevel@tonic-gate bferr("Ambiguous"); 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate cp = savestr(gargv[0]); 1077c478bd9Sstevel@tonic-gate blkfree(gargv), gargv = 0; 1087c478bd9Sstevel@tonic-gate return (cp); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * Subroutine to do actual fixing after state initialization. 1137c478bd9Sstevel@tonic-gate */ 1146c02b4a4Smuffin void 1156c02b4a4Smuffin Dfix2(tchar **v) 1167c478bd9Sstevel@tonic-gate { 1177c478bd9Sstevel@tonic-gate tchar *agargv[GAVSIZ]; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate #ifdef TRACE 1207c478bd9Sstevel@tonic-gate tprintf("TRACE- Dfix2()\n"); 1217c478bd9Sstevel@tonic-gate #endif 1227c478bd9Sstevel@tonic-gate ginit(agargv); /* Initialize glob's area pointers */ 123*65b0c20eSnakanon Dvp = v; Dcp = S_ /* "" */; /* Setup input vector for Dreadc */ 1247c478bd9Sstevel@tonic-gate unDgetC(0); unDredc(0); /* Clear out any old peeks (at error) */ 1257c478bd9Sstevel@tonic-gate dolp = 0; dolcnt = 0; /* Clear out residual $ expands (...) */ 1267c478bd9Sstevel@tonic-gate while (Dword()) 1277c478bd9Sstevel@tonic-gate continue; 1287c478bd9Sstevel@tonic-gate gargv = copyblk(gargv); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * Get a word. This routine is analogous to the routine 1337c478bd9Sstevel@tonic-gate * word() in sh.lex.c for the main lexical input. One difference 1347c478bd9Sstevel@tonic-gate * here is that we don't get a newline to terminate our expansion. 1357c478bd9Sstevel@tonic-gate * Rather, DgetC will return a DEOF when we hit the end-of-input. 1367c478bd9Sstevel@tonic-gate */ 1376c02b4a4Smuffin int 1386c02b4a4Smuffin Dword(void) 1397c478bd9Sstevel@tonic-gate { 1406c02b4a4Smuffin int c, c1; 1417c478bd9Sstevel@tonic-gate static tchar *wbuf = NULL; 1427c478bd9Sstevel@tonic-gate static int wbufsiz = BUFSIZ; 1436c02b4a4Smuffin int wp = 0; 1446c02b4a4Smuffin bool dolflg; 1457c478bd9Sstevel@tonic-gate bool sofar = 0; 1467c478bd9Sstevel@tonic-gate #define DYNAMICBUFFER() \ 1477c478bd9Sstevel@tonic-gate do { \ 1487c478bd9Sstevel@tonic-gate if (wp >= wbufsiz) { \ 1497c478bd9Sstevel@tonic-gate wbufsiz += BUFSIZ; \ 1507c478bd9Sstevel@tonic-gate wbuf = xrealloc(wbuf, (wbufsiz+1) * sizeof (tchar)); \ 1517c478bd9Sstevel@tonic-gate } \ 1527c478bd9Sstevel@tonic-gate } while (0) 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate #ifdef TRACE 1557c478bd9Sstevel@tonic-gate tprintf("TRACE- Dword()\n"); 1567c478bd9Sstevel@tonic-gate #endif 1577c478bd9Sstevel@tonic-gate if (wbuf == NULL) 1587c478bd9Sstevel@tonic-gate wbuf = xalloc((wbufsiz+1) * sizeof (tchar)); 1597c478bd9Sstevel@tonic-gate loop: 1607c478bd9Sstevel@tonic-gate c = DgetC(DODOL); 1617c478bd9Sstevel@tonic-gate switch (c) { 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate case DEOF: 1647c478bd9Sstevel@tonic-gate deof: 1657c478bd9Sstevel@tonic-gate if (sofar == 0) 1667c478bd9Sstevel@tonic-gate return (0); 1677c478bd9Sstevel@tonic-gate /* finish this word and catch the code above the next time */ 1687c478bd9Sstevel@tonic-gate unDredc(c); 1697c478bd9Sstevel@tonic-gate /* fall into ... */ 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate case '\n': 1727c478bd9Sstevel@tonic-gate wbuf[wp] = 0; 1737c478bd9Sstevel@tonic-gate goto ret; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate case ' ': 1767c478bd9Sstevel@tonic-gate case '\t': 1777c478bd9Sstevel@tonic-gate goto loop; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate case '`': 1807c478bd9Sstevel@tonic-gate /* We preserve ` quotations which are done yet later */ 1817c478bd9Sstevel@tonic-gate wbuf[wp++] = c; 1827c478bd9Sstevel@tonic-gate case '\'': 1837c478bd9Sstevel@tonic-gate case '"': 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * Note that DgetC never returns a QUOTES character 1867c478bd9Sstevel@tonic-gate * from an expansion, so only true input quotes will 1877c478bd9Sstevel@tonic-gate * get us here or out. 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate c1 = c; 1907c478bd9Sstevel@tonic-gate dolflg = c1 == '"' ? DODOL : 0; 1917c478bd9Sstevel@tonic-gate for (;;) { 1927c478bd9Sstevel@tonic-gate c = DgetC(dolflg); 1937c478bd9Sstevel@tonic-gate if (c == c1) 1947c478bd9Sstevel@tonic-gate break; 1957c478bd9Sstevel@tonic-gate if (c == '\n' || c == DEOF) 1967c478bd9Sstevel@tonic-gate error("Unmatched %c", (tchar) c1); 1977c478bd9Sstevel@tonic-gate if ((c & (QUOTE|TRIM)) == ('\n' | QUOTE)) 1987c478bd9Sstevel@tonic-gate --wp; 1997c478bd9Sstevel@tonic-gate DYNAMICBUFFER(); 2007c478bd9Sstevel@tonic-gate switch (c1) { 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate case '"': 2037c478bd9Sstevel@tonic-gate /* 2047c478bd9Sstevel@tonic-gate * Leave any `s alone for later. 2057c478bd9Sstevel@tonic-gate * Other chars are all quoted, thus `...` 2067c478bd9Sstevel@tonic-gate * can tell it was within "...". 2077c478bd9Sstevel@tonic-gate */ 2087c478bd9Sstevel@tonic-gate wbuf[wp++] = c == '`' ? '`' : c | QUOTE; 2097c478bd9Sstevel@tonic-gate break; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate case '\'': 2127c478bd9Sstevel@tonic-gate /* Prevent all further interpretation */ 2137c478bd9Sstevel@tonic-gate wbuf[wp++] = c | QUOTE; 2147c478bd9Sstevel@tonic-gate break; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate case '`': 2177c478bd9Sstevel@tonic-gate /* Leave all text alone for later */ 2187c478bd9Sstevel@tonic-gate wbuf[wp++] = c; 2197c478bd9Sstevel@tonic-gate break; 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate if (c1 == '`') { 2237c478bd9Sstevel@tonic-gate DYNAMICBUFFER(); 2247c478bd9Sstevel@tonic-gate wbuf[wp++] = '`'; 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate goto pack; /* continue the word */ 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate case '\\': 2297c478bd9Sstevel@tonic-gate c = DgetC(0); /* No $ subst! */ 2307c478bd9Sstevel@tonic-gate if (c == '\n' || c == DEOF) 2317c478bd9Sstevel@tonic-gate goto loop; 2327c478bd9Sstevel@tonic-gate c |= QUOTE; 2337c478bd9Sstevel@tonic-gate break; 2347c478bd9Sstevel@tonic-gate #ifdef MBCHAR /* Could be a space char from aux. codeset. */ 2357c478bd9Sstevel@tonic-gate default: 2367c478bd9Sstevel@tonic-gate if (isauxsp(c)) goto loop; 2377c478bd9Sstevel@tonic-gate #endif /* MBCHAR */ 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate unDgetC(c); 2407c478bd9Sstevel@tonic-gate pack: 2417c478bd9Sstevel@tonic-gate sofar = 1; 2427c478bd9Sstevel@tonic-gate /* pack up more characters in this word */ 2437c478bd9Sstevel@tonic-gate for (;;) { 2447c478bd9Sstevel@tonic-gate c = DgetC(DODOL); 2457c478bd9Sstevel@tonic-gate if (c == '\\') { 2467c478bd9Sstevel@tonic-gate c = DgetC(0); 2477c478bd9Sstevel@tonic-gate if (c == DEOF) 2487c478bd9Sstevel@tonic-gate goto deof; 2497c478bd9Sstevel@tonic-gate if (c == '\n') 2507c478bd9Sstevel@tonic-gate c = ' '; 2517c478bd9Sstevel@tonic-gate else 2527c478bd9Sstevel@tonic-gate c |= QUOTE; 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate if (c == DEOF) 2557c478bd9Sstevel@tonic-gate goto deof; 2567c478bd9Sstevel@tonic-gate if (cmap(c, _SP|_NL|_Q|_Q1) || 2577c478bd9Sstevel@tonic-gate isauxsp(c)) { /* sp \t\n'"` or aux. sp */ 2587c478bd9Sstevel@tonic-gate unDgetC(c); 2597c478bd9Sstevel@tonic-gate if (cmap(c, QUOTES)) 2607c478bd9Sstevel@tonic-gate goto loop; 2617c478bd9Sstevel@tonic-gate DYNAMICBUFFER(); 2627c478bd9Sstevel@tonic-gate wbuf[wp++] = 0; 2637c478bd9Sstevel@tonic-gate goto ret; 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate DYNAMICBUFFER(); 2667c478bd9Sstevel@tonic-gate wbuf[wp++] = c; 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate ret: 2697c478bd9Sstevel@tonic-gate Gcat(S_ /* "" */, wbuf); 2707c478bd9Sstevel@tonic-gate return (1); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* 2747c478bd9Sstevel@tonic-gate * Get a character, performing $ substitution unless flag is 0. 2757c478bd9Sstevel@tonic-gate * Any QUOTES character which is returned from a $ expansion is 2767c478bd9Sstevel@tonic-gate * QUOTEd so that it will not be recognized above. 2777c478bd9Sstevel@tonic-gate */ 2786c02b4a4Smuffin int 2796c02b4a4Smuffin DgetC(int flag) 2807c478bd9Sstevel@tonic-gate { 2816c02b4a4Smuffin int c; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate top: 2847c478bd9Sstevel@tonic-gate if (c = Dpeekc) { 2857c478bd9Sstevel@tonic-gate Dpeekc = 0; 2867c478bd9Sstevel@tonic-gate return (c); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate if (lap) { 2897c478bd9Sstevel@tonic-gate c = *lap++ & (QUOTE|TRIM); 2907c478bd9Sstevel@tonic-gate if (c == 0) { 2917c478bd9Sstevel@tonic-gate lap = 0; 2927c478bd9Sstevel@tonic-gate goto top; 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate quotspec: 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * don't quote things if there was an error (err!=0) 2977c478bd9Sstevel@tonic-gate * the input is original, not from a substitution and 2987c478bd9Sstevel@tonic-gate * therefore should not be quoted 2997c478bd9Sstevel@tonic-gate */ 3007c478bd9Sstevel@tonic-gate if (!err && cmap(c, QUOTES)) 3017c478bd9Sstevel@tonic-gate return (c | QUOTE); 3027c478bd9Sstevel@tonic-gate return (c); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate if (dolp) { 3057c478bd9Sstevel@tonic-gate if (c = *dolp++ & (QUOTE|TRIM)) 3067c478bd9Sstevel@tonic-gate goto quotspec; 3077c478bd9Sstevel@tonic-gate if (dolcnt > 0) { 3087c478bd9Sstevel@tonic-gate setDolp(*dolnxt++); 3097c478bd9Sstevel@tonic-gate --dolcnt; 3107c478bd9Sstevel@tonic-gate return (' '); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate dolp = 0; 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate if (dolcnt > 0) { 3157c478bd9Sstevel@tonic-gate setDolp(*dolnxt++); 3167c478bd9Sstevel@tonic-gate --dolcnt; 3177c478bd9Sstevel@tonic-gate goto top; 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate c = Dredc(); 3207c478bd9Sstevel@tonic-gate if (c == '$' && flag) { 3217c478bd9Sstevel@tonic-gate Dgetdol(); 3227c478bd9Sstevel@tonic-gate goto top; 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate return (c); 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate tchar *nulvec[] = { 0 }; 3287c478bd9Sstevel@tonic-gate struct varent nulargv = { nulvec, S_argv, 0 }; 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* 3317c478bd9Sstevel@tonic-gate * Handle the multitudinous $ expansion forms. 3327c478bd9Sstevel@tonic-gate * Ugh. 3337c478bd9Sstevel@tonic-gate */ 3346c02b4a4Smuffin void 3356c02b4a4Smuffin Dgetdol(void) 3367c478bd9Sstevel@tonic-gate { 3376c02b4a4Smuffin tchar *np; 3386c02b4a4Smuffin struct varent *vp; 3397c478bd9Sstevel@tonic-gate tchar name[MAX_VREF_LEN]; 3407c478bd9Sstevel@tonic-gate int c, sc; 3417c478bd9Sstevel@tonic-gate int subscr = 0, lwb = 1, upb = 0; 3427c478bd9Sstevel@tonic-gate bool dimen = 0, bitset = 0; 343*65b0c20eSnakanon tchar wbuf[BUFSIZ + MB_LEN_MAX]; /* read_ may return extra bytes */ 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate #ifdef TRACE 3467c478bd9Sstevel@tonic-gate tprintf("TRACE- Dgetdol()\n"); 3477c478bd9Sstevel@tonic-gate #endif 3487c478bd9Sstevel@tonic-gate dolmod = dolmcnt = 0; 3497c478bd9Sstevel@tonic-gate c = sc = DgetC(0); 3507c478bd9Sstevel@tonic-gate if (c == '{') 3517c478bd9Sstevel@tonic-gate c = DgetC(0); /* sc is { to take } later */ 3527c478bd9Sstevel@tonic-gate if ((c & TRIM) == '#') 3537c478bd9Sstevel@tonic-gate dimen++, c = DgetC(0); /* $# takes dimension */ 3547c478bd9Sstevel@tonic-gate else if (c == '?') 3557c478bd9Sstevel@tonic-gate bitset++, c = DgetC(0); /* $? tests existence */ 3567c478bd9Sstevel@tonic-gate switch (c) { 357*65b0c20eSnakanon 3587c478bd9Sstevel@tonic-gate case '$': 3597c478bd9Sstevel@tonic-gate if (dimen || bitset) 3607c478bd9Sstevel@tonic-gate syntax: 3617c478bd9Sstevel@tonic-gate error("Variable syntax"); /* No $?$, $#$ */ 3627c478bd9Sstevel@tonic-gate setDolp(doldol); 3637c478bd9Sstevel@tonic-gate goto eatbrac; 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate case '<'|QUOTE: 3667c478bd9Sstevel@tonic-gate if (dimen || bitset) 3677c478bd9Sstevel@tonic-gate goto syntax; /* No $?<, $#< */ 3687c478bd9Sstevel@tonic-gate for (np = wbuf; read_(OLDSTD, np, 1) == 1; np++) { 3697c478bd9Sstevel@tonic-gate if (np >= &wbuf[BUFSIZ-1]) 3707c478bd9Sstevel@tonic-gate error("$< line too long"); 3717c478bd9Sstevel@tonic-gate if (*np <= 0 || *np == '\n') 3727c478bd9Sstevel@tonic-gate break; 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate *np = 0; 3757c478bd9Sstevel@tonic-gate /* 3767c478bd9Sstevel@tonic-gate * KLUDGE: dolmod is set here because it will 3777c478bd9Sstevel@tonic-gate * cause setDolp to call domod and thus to copy wbuf. 3787c478bd9Sstevel@tonic-gate * Otherwise setDolp would use it directly. If we saved 3797c478bd9Sstevel@tonic-gate * it ourselves, no one would know when to free it. 3807c478bd9Sstevel@tonic-gate * The actual function of the 'q' causes filename 3817c478bd9Sstevel@tonic-gate * expansion not to be done on the interpolated value. 3827c478bd9Sstevel@tonic-gate */ 3837c478bd9Sstevel@tonic-gate dolmod = 'q'; 3847c478bd9Sstevel@tonic-gate dolmcnt = 10000; 3857c478bd9Sstevel@tonic-gate setDolp(wbuf); 3867c478bd9Sstevel@tonic-gate goto eatbrac; 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate case DEOF: 3897c478bd9Sstevel@tonic-gate case '\n': 3907c478bd9Sstevel@tonic-gate goto syntax; 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate case '*': 3937c478bd9Sstevel@tonic-gate (void) strcpy_(name, S_argv); 3947c478bd9Sstevel@tonic-gate vp = adrof(S_argv); 3957c478bd9Sstevel@tonic-gate subscr = -1; /* Prevent eating [...] */ 3967c478bd9Sstevel@tonic-gate break; 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate default: 3997c478bd9Sstevel@tonic-gate np = name; 4007c478bd9Sstevel@tonic-gate if (digit(c)) { 4017c478bd9Sstevel@tonic-gate if (dimen) 4027c478bd9Sstevel@tonic-gate goto syntax; /* No $#1, e.g. */ 4037c478bd9Sstevel@tonic-gate subscr = 0; 4047c478bd9Sstevel@tonic-gate do { 4057c478bd9Sstevel@tonic-gate subscr = subscr * 10 + c - '0'; 4067c478bd9Sstevel@tonic-gate c = DgetC(0); 4077c478bd9Sstevel@tonic-gate } while (digit(c)); 4087c478bd9Sstevel@tonic-gate unDredc(c); 4097c478bd9Sstevel@tonic-gate if (subscr < 0) 4107c478bd9Sstevel@tonic-gate error("Subscript out of range"); 4117c478bd9Sstevel@tonic-gate if (subscr == 0) { 4127c478bd9Sstevel@tonic-gate if (bitset) { 413*65b0c20eSnakanon dolp = file ? S_1 /* "1" */ : S_0 /* "0" */; 4147c478bd9Sstevel@tonic-gate goto eatbrac; 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate if (file == 0) 4177c478bd9Sstevel@tonic-gate error("No file for $0"); 4187c478bd9Sstevel@tonic-gate setDolp(file); 4197c478bd9Sstevel@tonic-gate goto eatbrac; 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate if (bitset) 4227c478bd9Sstevel@tonic-gate goto syntax; 4237c478bd9Sstevel@tonic-gate vp = adrof(S_argv); 4247c478bd9Sstevel@tonic-gate if (vp == 0) { 4257c478bd9Sstevel@tonic-gate vp = &nulargv; 4267c478bd9Sstevel@tonic-gate goto eatmod; 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate break; 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate if (!alnum(c)) 4317c478bd9Sstevel@tonic-gate goto syntax; 4327c478bd9Sstevel@tonic-gate for (;;) { 4337c478bd9Sstevel@tonic-gate *np++ = c; 4347c478bd9Sstevel@tonic-gate c = DgetC(0); 4357c478bd9Sstevel@tonic-gate if (!alnum(c)) 4367c478bd9Sstevel@tonic-gate break; 4377c478bd9Sstevel@tonic-gate /* if variable name is > 20, complain */ 4387c478bd9Sstevel@tonic-gate if (np >= &name[MAX_VAR_LEN]) 4397c478bd9Sstevel@tonic-gate error("Variable name too long"); 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate *np++ = 0; 4437c478bd9Sstevel@tonic-gate unDredc(c); 4447c478bd9Sstevel@tonic-gate vp = adrof(name); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate if (bitset) { 447*65b0c20eSnakanon /* 448*65b0c20eSnakanon * getenv() to getenv_(), because 'name''s type is now tchar * 449*65b0c20eSnakanon * no need to xalloc 450*65b0c20eSnakanon */ 451*65b0c20eSnakanon dolp = (vp || getenv_(name)) ? S_1 /* "1" */ : S_0 /* "0" */; 4527c478bd9Sstevel@tonic-gate goto eatbrac; 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate if (vp == 0) { 455*65b0c20eSnakanon /* 456*65b0c20eSnakanon * getenv() to getenv_(), because 'name''s type is now tchar * 457*65b0c20eSnakanon * no need to xalloc 458*65b0c20eSnakanon */ 4597c478bd9Sstevel@tonic-gate np = getenv_(name); 4607c478bd9Sstevel@tonic-gate if (np) { 4617c478bd9Sstevel@tonic-gate addla(np); 4627c478bd9Sstevel@tonic-gate goto eatbrac; 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate udvar(name); 4657c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate c = DgetC(0); 4687c478bd9Sstevel@tonic-gate upb = blklen(vp->vec); 4697c478bd9Sstevel@tonic-gate if (dimen == 0 && subscr == 0 && c == '[') { 4707c478bd9Sstevel@tonic-gate np = name; 4717c478bd9Sstevel@tonic-gate for (;;) { 4727c478bd9Sstevel@tonic-gate c = DgetC(DODOL); /* Allow $ expand within [ ] */ 4737c478bd9Sstevel@tonic-gate if (c == ']') 4747c478bd9Sstevel@tonic-gate break; 4757c478bd9Sstevel@tonic-gate if (c == '\n' || c == DEOF) 4767c478bd9Sstevel@tonic-gate goto syntax; 4777c478bd9Sstevel@tonic-gate if (np >= &name[MAX_VREF_LEN]) 4787c478bd9Sstevel@tonic-gate error("Variable reference too long"); 4797c478bd9Sstevel@tonic-gate *np++ = c; 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate *np = 0, np = name; 4827c478bd9Sstevel@tonic-gate if (dolp || dolcnt) /* $ exp must end before ] */ 4837c478bd9Sstevel@tonic-gate goto syntax; 4847c478bd9Sstevel@tonic-gate if (!*np) 4857c478bd9Sstevel@tonic-gate goto syntax; 4867c478bd9Sstevel@tonic-gate if (digit(*np)) { 4876c02b4a4Smuffin int i = 0; 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate while (digit(*np)) 4907c478bd9Sstevel@tonic-gate i = i * 10 + *np++ - '0'; 491*65b0c20eSnakanon /* if ((i < 0 || i > upb) && !any(*np, "-*")) { */ 492*65b0c20eSnakanon if ((i < 0 || i > upb) && (*np != '-') && (*np != '*')) { 4937c478bd9Sstevel@tonic-gate oob: 4947c478bd9Sstevel@tonic-gate setname(vp->v_name); 4957c478bd9Sstevel@tonic-gate error("Subscript out of range"); 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate lwb = i; 4987c478bd9Sstevel@tonic-gate if (!*np) 499*65b0c20eSnakanon upb = lwb, np = S_AST /* "*" */; 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate if (*np == '*') 5027c478bd9Sstevel@tonic-gate np++; 5037c478bd9Sstevel@tonic-gate else if (*np != '-') 5047c478bd9Sstevel@tonic-gate goto syntax; 5057c478bd9Sstevel@tonic-gate else { 5066c02b4a4Smuffin int i = upb; 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate np++; 5097c478bd9Sstevel@tonic-gate if (digit(*np)) { 5107c478bd9Sstevel@tonic-gate i = 0; 5117c478bd9Sstevel@tonic-gate while (digit(*np)) 5127c478bd9Sstevel@tonic-gate i = i * 10 + *np++ - '0'; 5137c478bd9Sstevel@tonic-gate if (i < 0 || i > upb) 5147c478bd9Sstevel@tonic-gate goto oob; 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate if (i < lwb) 5177c478bd9Sstevel@tonic-gate upb = lwb - 1; 5187c478bd9Sstevel@tonic-gate else 5197c478bd9Sstevel@tonic-gate upb = i; 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate if (lwb == 0) { 5227c478bd9Sstevel@tonic-gate if (upb != 0) 5237c478bd9Sstevel@tonic-gate goto oob; 5247c478bd9Sstevel@tonic-gate upb = -1; 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate if (*np) 5277c478bd9Sstevel@tonic-gate goto syntax; 5287c478bd9Sstevel@tonic-gate } else { 5297c478bd9Sstevel@tonic-gate if (subscr > 0) 5307c478bd9Sstevel@tonic-gate if (subscr > upb) 5317c478bd9Sstevel@tonic-gate lwb = 1, upb = 0; 5327c478bd9Sstevel@tonic-gate else 5337c478bd9Sstevel@tonic-gate lwb = upb = subscr; 5347c478bd9Sstevel@tonic-gate unDredc(c); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate if (dimen) { 5377c478bd9Sstevel@tonic-gate tchar *cp = putn(upb - lwb + 1); 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate addla(cp); 5407c478bd9Sstevel@tonic-gate xfree(cp); 5417c478bd9Sstevel@tonic-gate } else { 5427c478bd9Sstevel@tonic-gate eatmod: 5437c478bd9Sstevel@tonic-gate c = DgetC(0); 5447c478bd9Sstevel@tonic-gate if (c == ':') { 5457c478bd9Sstevel@tonic-gate c = DgetC(0), dolmcnt = 1; 5467c478bd9Sstevel@tonic-gate if (c == 'g') 5477c478bd9Sstevel@tonic-gate c = DgetC(0), dolmcnt = 10000; 5487c478bd9Sstevel@tonic-gate if (!any(c, S_htrqxe)) 5497c478bd9Sstevel@tonic-gate error("Bad : mod in $"); 5507c478bd9Sstevel@tonic-gate dolmod = c; 5517c478bd9Sstevel@tonic-gate if (c == 'q') 5527c478bd9Sstevel@tonic-gate dolmcnt = 10000; 5537c478bd9Sstevel@tonic-gate } else 5547c478bd9Sstevel@tonic-gate unDredc(c); 5557c478bd9Sstevel@tonic-gate dolnxt = &vp->vec[lwb - 1]; 5567c478bd9Sstevel@tonic-gate dolcnt = upb - lwb + 1; 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate eatbrac: 5597c478bd9Sstevel@tonic-gate if (sc == '{') { 5607c478bd9Sstevel@tonic-gate c = Dredc(); 5617c478bd9Sstevel@tonic-gate if (c != '}') 5627c478bd9Sstevel@tonic-gate goto syntax; 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate 5666c02b4a4Smuffin void 5676c02b4a4Smuffin setDolp(tchar *cp) 5687c478bd9Sstevel@tonic-gate { 5696c02b4a4Smuffin tchar *dp; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate #ifdef TRACE 5727c478bd9Sstevel@tonic-gate tprintf("TRACE- setDolp()\n"); 5737c478bd9Sstevel@tonic-gate #endif 5747c478bd9Sstevel@tonic-gate if (dolmod == 0 || dolmcnt == 0) { 5757c478bd9Sstevel@tonic-gate dolp = cp; 5767c478bd9Sstevel@tonic-gate return; 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate dp = domod(cp, dolmod); 5797c478bd9Sstevel@tonic-gate if (dp) { 5807c478bd9Sstevel@tonic-gate dolmcnt--; 5817c478bd9Sstevel@tonic-gate addla(dp); 5827c478bd9Sstevel@tonic-gate xfree(dp); 5837c478bd9Sstevel@tonic-gate } else 5847c478bd9Sstevel@tonic-gate addla(cp); 585*65b0c20eSnakanon dolp = S_ /* "" */; 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5886c02b4a4Smuffin void 5896c02b4a4Smuffin unDredc(int c) 5907c478bd9Sstevel@tonic-gate { 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate Dpeekrd = c; 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5956c02b4a4Smuffin int 5967c478bd9Sstevel@tonic-gate Dredc() 5977c478bd9Sstevel@tonic-gate { 5986c02b4a4Smuffin int c; 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate if (c = Dpeekrd) { 6017c478bd9Sstevel@tonic-gate Dpeekrd = 0; 6027c478bd9Sstevel@tonic-gate return (c); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate if (Dcp && (c = *Dcp++)) 6057c478bd9Sstevel@tonic-gate return (c&(QUOTE|TRIM)); 6067c478bd9Sstevel@tonic-gate if (*Dvp == 0) { 6077c478bd9Sstevel@tonic-gate Dcp = 0; 6087c478bd9Sstevel@tonic-gate return (DEOF); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate Dcp = *Dvp++; 6117c478bd9Sstevel@tonic-gate return (' '); 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate 6146c02b4a4Smuffin void 6156c02b4a4Smuffin Dtestq(int c) 6167c478bd9Sstevel@tonic-gate { 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate if (cmap(c, QUOTES)) 6197c478bd9Sstevel@tonic-gate gflag = 1; 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate /* 6237c478bd9Sstevel@tonic-gate * Form a shell temporary file (in unit 0) from the words 6247c478bd9Sstevel@tonic-gate * of the shell input up to a line the same as "term". 6257c478bd9Sstevel@tonic-gate * Unit 0 should have been closed before this call. 6267c478bd9Sstevel@tonic-gate */ 6276c02b4a4Smuffin void 6286c02b4a4Smuffin heredoc(tchar *term) 6297c478bd9Sstevel@tonic-gate { 6306c02b4a4Smuffin int c; 6317c478bd9Sstevel@tonic-gate tchar *Dv[2]; 6327c478bd9Sstevel@tonic-gate tchar obuf[BUFSIZ], lbuf[BUFSIZ], mbuf[BUFSIZ]; 6337c478bd9Sstevel@tonic-gate int ocnt, lcnt, mcnt; 6346c02b4a4Smuffin tchar *lbp, *obp, *mbp; 6357c478bd9Sstevel@tonic-gate tchar **vp; 6367c478bd9Sstevel@tonic-gate bool quoted; 6377c478bd9Sstevel@tonic-gate tchar shtemp[] = {'/', 't', 'm', 'p', '/', 's', 'h', 'X', 'X', 'X', 6387c478bd9Sstevel@tonic-gate 'X', 'X', 'X', 0}; 6397c478bd9Sstevel@tonic-gate int fd1; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate #ifdef TRACE 6427c478bd9Sstevel@tonic-gate tprintf("TRACE- heredoc()\n"); 6437c478bd9Sstevel@tonic-gate #endif 6447c478bd9Sstevel@tonic-gate if ((fd1 = mkstemp_(shtemp)) < 0) 6457c478bd9Sstevel@tonic-gate Perror(shtemp); 6467c478bd9Sstevel@tonic-gate (void) unlink_(shtemp); /* 0 0 inode! */ 6477c478bd9Sstevel@tonic-gate unsetfd(fd1); 6487c478bd9Sstevel@tonic-gate Dv[0] = term; Dv[1] = NOSTR; gflag = 0; 6497c478bd9Sstevel@tonic-gate trim(Dv); rscan(Dv, Dtestq); quoted = gflag; 6507c478bd9Sstevel@tonic-gate ocnt = BUFSIZ; obp = obuf; 6517c478bd9Sstevel@tonic-gate for (;;) { 6527c478bd9Sstevel@tonic-gate /* 6537c478bd9Sstevel@tonic-gate * Read up a line 6547c478bd9Sstevel@tonic-gate */ 6557c478bd9Sstevel@tonic-gate lbp = lbuf; lcnt = BUFSIZ - 4; 6567c478bd9Sstevel@tonic-gate for (;;) { 6577c478bd9Sstevel@tonic-gate c = readc(1); /* 1 -> Want EOF returns */ 6587c478bd9Sstevel@tonic-gate if (c < 0) { 6597c478bd9Sstevel@tonic-gate setname(term); 6607c478bd9Sstevel@tonic-gate bferr("<< terminator not found"); 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate if (c == '\n') 6637c478bd9Sstevel@tonic-gate break; 6647c478bd9Sstevel@tonic-gate if (c &= TRIM) { 6657c478bd9Sstevel@tonic-gate *lbp++ = c; 6667c478bd9Sstevel@tonic-gate if (--lcnt < 0) { 667*65b0c20eSnakanon setname(S_LESLES /* "<<" */); 6687c478bd9Sstevel@tonic-gate error("Line overflow"); 669*65b0c20eSnakanon } 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate *lbp = 0; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate /* 6757c478bd9Sstevel@tonic-gate * Compare to terminator -- before expansion 6767c478bd9Sstevel@tonic-gate */ 6777c478bd9Sstevel@tonic-gate if (eq(lbuf, term)) { 6787c478bd9Sstevel@tonic-gate (void) write_(0, obuf, BUFSIZ - ocnt); 6797c478bd9Sstevel@tonic-gate (void) lseek(0, (off_t)0, 0); 6807c478bd9Sstevel@tonic-gate return; 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate /* 6847c478bd9Sstevel@tonic-gate * If term was quoted or -n just pass it on 6857c478bd9Sstevel@tonic-gate */ 6867c478bd9Sstevel@tonic-gate if (quoted || noexec) { 6877c478bd9Sstevel@tonic-gate *lbp++ = '\n'; *lbp = 0; 688*65b0c20eSnakanon for (lbp = lbuf; c = *lbp++; ) { 6897c478bd9Sstevel@tonic-gate *obp++ = c; 6907c478bd9Sstevel@tonic-gate if (--ocnt == 0) { 6917c478bd9Sstevel@tonic-gate (void) write_(0, obuf, BUFSIZ); 6927c478bd9Sstevel@tonic-gate obp = obuf; ocnt = BUFSIZ; 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate continue; 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate /* 6997c478bd9Sstevel@tonic-gate * Term wasn't quoted so variable and then command 7007c478bd9Sstevel@tonic-gate * expand the input line 7017c478bd9Sstevel@tonic-gate */ 7027c478bd9Sstevel@tonic-gate Dcp = lbuf; Dvp = Dv + 1; mbp = mbuf; mcnt = BUFSIZ - 4; 7037c478bd9Sstevel@tonic-gate for (;;) { 7047c478bd9Sstevel@tonic-gate c = DgetC(DODOL); 7057c478bd9Sstevel@tonic-gate if (c == DEOF) 7067c478bd9Sstevel@tonic-gate break; 7077c478bd9Sstevel@tonic-gate if ((c &= TRIM) == 0) 7087c478bd9Sstevel@tonic-gate continue; 7097c478bd9Sstevel@tonic-gate /* \ quotes \ $ ` here */ 710*65b0c20eSnakanon if (c == '\\') { 7117c478bd9Sstevel@tonic-gate c = DgetC(0); 712*65b0c20eSnakanon /* if (!any(c, "$\\`")) */ 713*65b0c20eSnakanon if ((c != '$') && (c != '\\') && (c != '`')) 7147c478bd9Sstevel@tonic-gate unDgetC(c | QUOTE), c = '\\'; 7157c478bd9Sstevel@tonic-gate else 7167c478bd9Sstevel@tonic-gate c |= QUOTE; 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate *mbp++ = c; 7197c478bd9Sstevel@tonic-gate if (--mcnt == 0) { 720*65b0c20eSnakanon setname(S_LESLES /* "<<" */); 7217c478bd9Sstevel@tonic-gate bferr("Line overflow"); 7227c478bd9Sstevel@tonic-gate } 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate *mbp++ = 0; 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate /* 7277c478bd9Sstevel@tonic-gate * If any ` in line do command substitution 7287c478bd9Sstevel@tonic-gate */ 7297c478bd9Sstevel@tonic-gate mbp = mbuf; 7307c478bd9Sstevel@tonic-gate if (any('`', mbp)) { 7317c478bd9Sstevel@tonic-gate /* 7327c478bd9Sstevel@tonic-gate * 1 arg to dobackp causes substitution to be literal. 7337c478bd9Sstevel@tonic-gate * Words are broken only at newlines so that all blanks 7347c478bd9Sstevel@tonic-gate * and tabs are preserved. Blank lines (null words) 7357c478bd9Sstevel@tonic-gate * are not discarded. 7367c478bd9Sstevel@tonic-gate */ 7377c478bd9Sstevel@tonic-gate vp = dobackp(mbuf, 1); 7387c478bd9Sstevel@tonic-gate } else 7397c478bd9Sstevel@tonic-gate /* Setup trivial vector similar to return of dobackp */ 7407c478bd9Sstevel@tonic-gate Dv[0] = mbp, Dv[1] = NOSTR, vp = Dv; 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate /* 7437c478bd9Sstevel@tonic-gate * Resurrect the words from the command substitution 7447c478bd9Sstevel@tonic-gate * each separated by a newline. Note that the last 7457c478bd9Sstevel@tonic-gate * newline of a command substitution will have been 7467c478bd9Sstevel@tonic-gate * discarded, but we put a newline after the last word 7477c478bd9Sstevel@tonic-gate * because this represents the newline after the last 7487c478bd9Sstevel@tonic-gate * input line! 7497c478bd9Sstevel@tonic-gate */ 7507c478bd9Sstevel@tonic-gate for (; *vp; vp++) { 7517c478bd9Sstevel@tonic-gate for (mbp = *vp; *mbp; mbp++) { 7527c478bd9Sstevel@tonic-gate *obp++ = *mbp & TRIM; 7537c478bd9Sstevel@tonic-gate if (--ocnt == 0) { 7547c478bd9Sstevel@tonic-gate (void) write_(0, obuf, BUFSIZ); 7557c478bd9Sstevel@tonic-gate obp = obuf; ocnt = BUFSIZ; 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate *obp++ = '\n'; 7597c478bd9Sstevel@tonic-gate if (--ocnt == 0) { 7607c478bd9Sstevel@tonic-gate (void) write_(0, obuf, BUFSIZ); 7617c478bd9Sstevel@tonic-gate obp = obuf; ocnt = BUFSIZ; 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate if (pargv) 7657c478bd9Sstevel@tonic-gate blkfree(pargv), pargv = 0; 7667c478bd9Sstevel@tonic-gate } 7677c478bd9Sstevel@tonic-gate } 768