diff options
Diffstat (limited to 'contrib/tcsh/sh.dol.c')
-rw-r--r-- | contrib/tcsh/sh.dol.c | 1094 |
1 files changed, 0 insertions, 1094 deletions
diff --git a/contrib/tcsh/sh.dol.c b/contrib/tcsh/sh.dol.c deleted file mode 100644 index 73ac3b2..0000000 --- a/contrib/tcsh/sh.dol.c +++ /dev/null @@ -1,1094 +0,0 @@ -/* $Header: /p/tcsh/cvsroot/tcsh/sh.dol.c,v 3.70 2006/09/14 18:30:16 christos Exp $ */ -/* - * sh.dol.c: Variable substitutions - */ -/*- - * Copyright (c) 1980, 1991 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#include "sh.h" - -RCSID("$tcsh: sh.dol.c,v 3.70 2006/09/14 18:30:16 christos Exp $") - -/* - * C shell - */ - -/* - * These routines perform variable substitution and quoting via ' and ". - * To this point these constructs have been preserved in the divided - * input words. Here we expand variables and turn quoting via ' and " into - * QUOTE bits on characters (which prevent further interpretation). - * If the `:q' modifier was applied during history expansion, then - * some QUOTEing may have occurred already, so we dont "trim()" here. - */ - -static Char Dpeekc; /* Peek for DgetC */ -static eChar Dpeekrd; /* Peek for Dreadc */ -static Char *Dcp, *const *Dvp; /* Input vector for Dreadc */ - -#define DEOF CHAR_ERR - -#define unDgetC(c) Dpeekc = c - -#define QUOTES (_QF|_QB|_ESC) /* \ ' " ` */ - -/* - * The following variables give the information about the current - * $ expansion, recording the current word position, the remaining - * words within this expansion, the count of remaining words, and the - * information about any : modifier which is being applied. - */ -static Char *dolp; /* Remaining chars from this word */ -static Char **dolnxt; /* Further words */ -static int dolcnt; /* Count of further words */ -static struct Strbuf dolmod; /* = Strbuf_INIT; : modifier characters */ -static int dolmcnt; /* :gx -> INT_MAX, else 1 */ -static int dol_flag_a; /* :ax -> 1, else 0 */ - -static Char **Dfix2 (Char *const *); -static int Dpack (struct Strbuf *); -static int Dword (struct blk_buf *); -static void dolerror (Char *); -static eChar DgetC (int); -static void Dgetdol (void); -static void fixDolMod (void); -static void setDolp (Char *); -static void unDredc (eChar); -static eChar Dredc (void); -static void Dtestq (Char); - -/* - * Fix up the $ expansions and quotations in the - * argument list to command t. - */ -void -Dfix(struct command *t) -{ - Char **pp; - Char *p; - - if (noexec) - return; - /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */ - for (pp = t->t_dcom; (p = *pp++) != NULL;) { - for (; *p; p++) { - if (cmap(*p, _DOL | QUOTES)) { /* $, \, ', ", ` */ - Char **expanded; - - expanded = Dfix2(t->t_dcom); /* found one */ - blkfree(t->t_dcom); - t->t_dcom = expanded; - return; - } - } - } -} - -/* - * $ substitute one word, for i/o redirection - */ -Char * -Dfix1(Char *cp) -{ - Char *Dv[2], **expanded; - - if (noexec) - return (0); - Dv[0] = cp; - Dv[1] = NULL; - expanded = Dfix2(Dv); - if (expanded[0] == NULL || expanded[1] != NULL) { - blkfree(expanded); - setname(short2str(cp)); - stderror(ERR_NAME | ERR_AMBIG); - } - cp = Strsave(expanded[0]); - blkfree(expanded); - return (cp); -} - -/* - * Subroutine to do actual fixing after state initialization. - */ -static Char ** -Dfix2(Char *const *v) -{ - struct blk_buf bb = BLK_BUF_INIT; - - Dvp = v; - Dcp = STRNULL; /* Setup input vector for Dreadc */ - unDgetC(0); - unDredc(0); /* Clear out any old peeks (at error) */ - dolp = 0; - dolcnt = 0; /* Clear out residual $ expands (...) */ - cleanup_push(&bb, bb_cleanup); - while (Dword(&bb)) - continue; - cleanup_ignore(&bb); - cleanup_until(&bb); - return bb_finish(&bb); -} - -/* - * Pack up more characters in this word - */ -static int -Dpack(struct Strbuf *wbuf) -{ - eChar c; - - for (;;) { - c = DgetC(DODOL); - if (c == '\\') { - c = DgetC(0); - if (c == DEOF) { - unDredc(c); - return 1; - } - if (c == '\n') - c = ' '; - else - c |= QUOTE; - } - if (c == DEOF) { - unDredc(c); - return 1; - } - if (cmap(c, _SP | _NL | _QF | _QB)) { /* sp \t\n'"` */ - unDgetC(c); - if (cmap(c, QUOTES)) - return 0; - return 1; - } - Strbuf_append1(wbuf, (Char) c); - } -} - -/* - * Get a word. This routine is analogous to the routine - * word() in sh.lex.c for the main lexical input. One difference - * here is that we don't get a newline to terminate our expansion. - * Rather, DgetC will return a DEOF when we hit the end-of-input. - */ -static int -Dword(struct blk_buf *bb) -{ - eChar c, c1; - struct Strbuf wbuf = Strbuf_INIT; - int dolflg; - int sofar = 0; - - cleanup_push(&wbuf, Strbuf_cleanup); - for (;;) { - c = DgetC(DODOL); - switch (c) { - - case DEOF: - if (sofar == 0) { - cleanup_until(&wbuf); - return (0); - } - /* finish this word and catch the code above the next time */ - unDredc(c); - /*FALLTHROUGH*/ - - case '\n': - goto end; - - case ' ': - case '\t': - continue; - - case '`': - /* We preserve ` quotations which are done yet later */ - Strbuf_append1(&wbuf, (Char) c); - /*FALLTHROUGH*/ - case '\'': - case '"': - /* - * Note that DgetC never returns a QUOTES character from an - * expansion, so only true input quotes will get us here or out. - */ - c1 = c; - dolflg = c1 == '"' ? DODOL : 0; - for (;;) { - c = DgetC(dolflg); - if (c == c1) - break; - if (c == '\n' || c == DEOF) - stderror(ERR_UNMATCHED, (int)c1); - if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE)) { - if (wbuf.len != 0 && (wbuf.s[wbuf.len - 1] & TRIM) == '\\') - wbuf.len--; - } - switch (c1) { - - case '"': - /* - * Leave any `s alone for later. Other chars are all - * quoted, thus `...` can tell it was within "...". - */ - Strbuf_append1(&wbuf, c == '`' ? '`' : c | QUOTE); - break; - - case '\'': - /* Prevent all further interpretation */ - Strbuf_append1(&wbuf, c | QUOTE); - break; - - case '`': - /* Leave all text alone for later */ - Strbuf_append1(&wbuf, (Char) c); - break; - - default: - break; - } - } - if (c1 == '`') - Strbuf_append1(&wbuf, '`'); - sofar = 1; - if (Dpack(&wbuf) != 0) - goto end; - continue; - - case '\\': - c = DgetC(0); /* No $ subst! */ - if (c == '\n' || c == DEOF) - continue; - c |= QUOTE; - break; - - default: - break; - } - unDgetC(c); - sofar = 1; - if (Dpack(&wbuf) != 0) - goto end; - } - - end: - cleanup_ignore(&wbuf); - cleanup_until(&wbuf); - bb_append(bb, Strbuf_finish(&wbuf)); - return 1; -} - - -/* - * Get a character, performing $ substitution unless flag is 0. - * Any QUOTES character which is returned from a $ expansion is - * QUOTEd so that it will not be recognized above. - */ -static eChar -DgetC(int flag) -{ - Char c; - -top: - if ((c = Dpeekc) != 0) { - Dpeekc = 0; - return (c); - } - if (lap < labuf.len) { - c = labuf.s[lap++] & (QUOTE | TRIM); -quotspec: - if (cmap(c, QUOTES)) - return (c | QUOTE); - return (c); - } - if (dolp) { - if ((c = *dolp++ & (QUOTE | TRIM)) != 0) - goto quotspec; - if (dolcnt > 0) { - setDolp(*dolnxt++); - --dolcnt; - return (' '); - } - dolp = 0; - } - if (dolcnt > 0) { - setDolp(*dolnxt++); - --dolcnt; - goto top; - } - c = Dredc(); - if (c == '$' && flag) { - Dgetdol(); - goto top; - } - return (c); -} - -static Char *nulvec[] = { NULL }; -static struct varent nulargv = {nulvec, STRargv, VAR_READWRITE, - { NULL, NULL, NULL }, 0 }; - -static void -dolerror(Char *s) -{ - setname(short2str(s)); - stderror(ERR_NAME | ERR_RANGE); -} - -/* - * Handle the multitudinous $ expansion forms. - * Ugh. - */ -static void -Dgetdol(void) -{ - Char *np; - struct varent *vp = NULL; - struct Strbuf name = Strbuf_INIT; - eChar c, sc; - int subscr = 0, lwb = 1, upb = 0; - int dimen = 0, bitset = 0, length = 0; - static Char *dolbang = NULL; - - cleanup_push(&name, Strbuf_cleanup); - dolmod.len = dolmcnt = dol_flag_a = 0; - c = sc = DgetC(0); - if (c == DEOF) { - stderror(ERR_SYNTAX); - return; - } - if (c == '{') - c = DgetC(0); /* sc is { to take } later */ - if ((c & TRIM) == '#') - dimen++, c = DgetC(0); /* $# takes dimension */ - else if (c == '?') - bitset++, c = DgetC(0); /* $? tests existence */ - else if (c == '%') - length++, c = DgetC(0); /* $% returns length in chars */ - switch (c) { - - case '!': - if (dimen || bitset || length) - stderror(ERR_SYNTAX); - if (backpid != 0) { - xfree(dolbang); - setDolp(dolbang = putn(backpid)); - } - cleanup_until(&name); - goto eatbrac; - - case '$': - if (dimen || bitset || length) - stderror(ERR_SYNTAX); - setDolp(doldol); - cleanup_until(&name); - goto eatbrac; - - case '<'|QUOTE: { - static struct Strbuf wbuf; /* = Strbuf_INIT; */ - - if (bitset) - stderror(ERR_NOTALLOWED, "$?<"); - if (dimen) - stderror(ERR_NOTALLOWED, "$#<"); - if (length) - stderror(ERR_NOTALLOWED, "$%<"); - wbuf.len = 0; - { - char cbuf[MB_LEN_MAX]; - size_t cbp = 0; - int old_pintr_disabled; - - for (;;) { - int len; - ssize_t res; - Char wc; - - pintr_push_enable(&old_pintr_disabled); - res = force_read(OLDSTD, cbuf + cbp, 1); - cleanup_until(&old_pintr_disabled); - if (res != 1) - break; - cbp++; - len = normal_mbtowc(&wc, cbuf, cbp); - if (len == -1) { - reset_mbtowc(); - if (cbp < MB_LEN_MAX) - continue; /* Maybe a partial character */ - wc = (unsigned char)*cbuf | INVALID_BYTE; - } - if (len <= 0) - len = 1; - if (cbp != (size_t)len) - memmove(cbuf, cbuf + len, cbp - len); - cbp -= len; - if (wc == '\n') - break; - Strbuf_append1(&wbuf, wc); - } - while (cbp != 0) { - int len; - Char wc; - - len = normal_mbtowc(&wc, cbuf, cbp); - if (len == -1) { - reset_mbtowc(); - wc = (unsigned char)*cbuf | INVALID_BYTE; - } - if (len <= 0) - len = 1; - if (cbp != (size_t)len) - memmove(cbuf, cbuf + len, cbp - len); - cbp -= len; - if (wc == '\n') - break; - Strbuf_append1(&wbuf, wc); - } - Strbuf_terminate(&wbuf); - } - - fixDolMod(); - setDolp(wbuf.s); /* Kept allocated until next $< expansion */ - cleanup_until(&name); - goto eatbrac; - } - - case '*': - Strbuf_append(&name, STRargv); - Strbuf_terminate(&name); - vp = adrof(STRargv); - subscr = -1; /* Prevent eating [...] */ - break; - - case DEOF: - case '\n': - np = dimen ? STRargv : (bitset ? STRstatus : NULL); - if (np) { - bitset = 0; - Strbuf_append(&name, np); - Strbuf_terminate(&name); - vp = adrof(np); - subscr = -1; /* Prevent eating [...] */ - unDredc(c); - break; - } - else - stderror(ERR_SYNTAX); - /*NOTREACHED*/ - - default: - if (Isdigit(c)) { - if (dimen) - stderror(ERR_NOTALLOWED, "$#<num>"); - subscr = 0; - do { - subscr = subscr * 10 + c - '0'; - c = DgetC(0); - } while (c != DEOF && Isdigit(c)); - unDredc(c); - if (subscr < 0) - stderror(ERR_RANGE); - if (subscr == 0) { - if (bitset) { - dolp = dolzero ? STR1 : STR0; - cleanup_until(&name); - goto eatbrac; - } - if (ffile == 0) - stderror(ERR_DOLZERO); - if (length) { - length = Strlen(ffile); - addla(putn(length)); - } - else { - fixDolMod(); - setDolp(ffile); - } - cleanup_until(&name); - goto eatbrac; - } -#if 0 - if (bitset) - stderror(ERR_NOTALLOWED, "$?<num>"); - if (length) - stderror(ERR_NOTALLOWED, "$%<num>"); -#endif - vp = adrof(STRargv); - if (vp == 0) { - vp = &nulargv; - cleanup_until(&name); - goto eatmod; - } - break; - } - if (c == DEOF || !alnum(c)) { - np = dimen ? STRargv : (bitset ? STRstatus : NULL); - if (np) { - bitset = 0; - Strbuf_append(&name, np); - Strbuf_terminate(&name); - vp = adrof(np); - subscr = -1; /* Prevent eating [...] */ - unDredc(c); - break; - } - else - stderror(ERR_VARALNUM); - } - for (;;) { - Strbuf_append1(&name, (Char) c); - c = DgetC(0); - if (c == DEOF || !alnum(c)) - break; - } - Strbuf_terminate(&name); - unDredc(c); - vp = adrof(name.s); - } - if (bitset) { - dolp = (vp || getenv(short2str(name.s))) ? STR1 : STR0; - cleanup_until(&name); - goto eatbrac; - } - if (vp == NULL || vp->vec == NULL) { - np = str2short(getenv(short2str(name.s))); - if (np) { - static Char *env_val; /* = NULL; */ - - cleanup_until(&name); - fixDolMod(); - xfree(env_val); - env_val = Strsave(np); - setDolp(env_val); - goto eatbrac; - } - udvar(name.s); - /* NOTREACHED */ - } - cleanup_until(&name); - c = DgetC(0); - upb = blklen(vp->vec); - if (dimen == 0 && subscr == 0 && c == '[') { - name = Strbuf_init; - cleanup_push(&name, Strbuf_cleanup); - np = name.s; - for (;;) { - c = DgetC(DODOL); /* Allow $ expand within [ ] */ - if (c == ']') - break; - if (c == '\n' || c == DEOF) - stderror(ERR_INCBR); - Strbuf_append1(&name, (Char) c); - } - Strbuf_terminate(&name); - np = name.s; - if (dolp || dolcnt) /* $ exp must end before ] */ - stderror(ERR_EXPORD); - if (!*np) - stderror(ERR_SYNTAX); - if (Isdigit(*np)) { - int i; - - for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0') - continue; - if ((i < 0 || i > upb) && !any("-*", *np)) { - cleanup_until(&name); - dolerror(vp->v_name); - return; - } - lwb = i; - if (!*np) - upb = lwb, np = STRstar; - } - if (*np == '*') - np++; - else if (*np != '-') - stderror(ERR_MISSING, '-'); - else { - int i = upb; - - np++; - if (Isdigit(*np)) { - i = 0; - while (Isdigit(*np)) - i = i * 10 + *np++ - '0'; - if (i < 0 || i > upb) { - cleanup_until(&name); - dolerror(vp->v_name); - return; - } - } - if (i < lwb) - upb = lwb - 1; - else - upb = i; - } - if (lwb == 0) { - if (upb != 0) { - cleanup_until(&name); - dolerror(vp->v_name); - return; - } - upb = -1; - } - if (*np) - stderror(ERR_SYNTAX); - cleanup_until(&name); - } - else { - if (subscr > 0) { - if (subscr > upb) - lwb = 1, upb = 0; - else - lwb = upb = subscr; - } - unDredc(c); - } - if (dimen) { - /* this is a kludge. It prevents Dgetdol() from */ - /* pushing erroneous ${#<error> values into the labuf. */ - if (sc == '{') { - c = Dredc(); - if (c != '}') - stderror(ERR_MISSING, '}'); - unDredc(c); - } - addla(putn(upb - lwb + 1)); - } - else if (length) { - int i; - - for (i = lwb - 1, length = 0; i < upb; i++) - length += Strlen(vp->vec[i]); -#ifdef notdef - /* We don't want that, since we can always compute it by adding $#xxx */ - length += i - 1; /* Add the number of spaces in */ -#endif - addla(putn(length)); - } - else { -eatmod: - fixDolMod(); - dolnxt = &vp->vec[lwb - 1]; - dolcnt = upb - lwb + 1; - } -eatbrac: - if (sc == '{') { - c = Dredc(); - if (c != '}') - stderror(ERR_MISSING, '}'); - } -} - -static void -fixDolMod(void) -{ - eChar c; - - c = DgetC(0); - if (c == ':') { - do { - c = DgetC(0), dolmcnt = 1, dol_flag_a = 0; - if (c == 'g' || c == 'a') { - if (c == 'g') - dolmcnt = INT_MAX; - else - dol_flag_a = 1; - c = DgetC(0); - } - if ((c == 'g' && dolmcnt != INT_MAX) || - (c == 'a' && dol_flag_a == 0)) { - if (c == 'g') - dolmcnt = INT_MAX; - else - dol_flag_a = 1; - c = DgetC(0); - } - - if (c == 's') { /* [eichin:19910926.0755EST] */ - int delimcnt = 2; - eChar delim = DgetC(0); - Strbuf_append1(&dolmod, (Char) c); - Strbuf_append1(&dolmod, (Char) delim); - - if (delim == DEOF || !delim || letter(delim) - || Isdigit(delim) || any(" \t\n", delim)) { - seterror(ERR_BADSUBST); - break; - } - while ((c = DgetC(0)) != DEOF) { - Strbuf_append1(&dolmod, (Char) c); - if(c == delim) delimcnt--; - if(!delimcnt) break; - } - if(delimcnt) { - seterror(ERR_BADSUBST); - break; - } - continue; - } - if (!any("luhtrqxes", c)) - stderror(ERR_BADMOD, (int)c); - Strbuf_append1(&dolmod, (Char) c); - if (c == 'q') - dolmcnt = INT_MAX; - } - while ((c = DgetC(0)) == ':'); - unDredc(c); - } - else - unDredc(c); -} - -static void -setDolp(Char *cp) -{ - Char *dp; - size_t i; - - if (dolmod.len == 0 || dolmcnt == 0) { - dolp = cp; - return; - } - cp = Strsave(cp); - for (i = 0; i < dolmod.len; i++) { - int didmod = 0; - - /* handle s// [eichin:19910926.0510EST] */ - if(dolmod.s[i] == 's') { - Char delim; - Char *lhsub, *rhsub, *np; - size_t lhlen = 0, rhlen = 0; - - delim = dolmod.s[++i]; - if (!delim || letter(delim) - || Isdigit(delim) || any(" \t\n", delim)) { - seterror(ERR_BADSUBST); - break; - } - lhsub = &dolmod.s[++i]; - while(dolmod.s[i] != delim && dolmod.s[++i]) { - lhlen++; - } - dolmod.s[i] = 0; - rhsub = &dolmod.s[++i]; - while(dolmod.s[i] != delim && dolmod.s[++i]) { - rhlen++; - } - dolmod.s[i] = 0; - - strip(lhsub); - strip(cp); - dp = cp; - do { - dp = Strstr(dp, lhsub); - if (dp) { - ptrdiff_t diff = dp - cp; - np = xmalloc((Strlen(cp) + 1 - lhlen + rhlen) * - sizeof(Char)); - (void) Strncpy(np, cp, diff); - (void) Strcpy(np + diff, rhsub); - (void) Strcpy(np + diff + rhlen, dp + lhlen); - - dp = np + diff + 1; - xfree(cp); - cp = np; - didmod = 1; - } else { - /* should this do a seterror? */ - break; - } - } - while (dol_flag_a != 0); - /* - * restore dolmod for additional words - */ - dolmod.s[i] = rhsub[-1] = (Char) delim; - } else { - - do { - if ((dp = domod(cp, dolmod.s[i])) != NULL) { - didmod = 1; - if (Strcmp(cp, dp) == 0) { - xfree(cp); - cp = dp; - break; - } - else { - xfree(cp); - cp = dp; - } - } - else - break; - } - while (dol_flag_a != 0); - } - if (didmod && dolmcnt != INT_MAX) - dolmcnt--; -#ifdef notdef - else - break; -#endif - } - - addla(cp); - - dolp = STRNULL; - if (seterr) - stderror(ERR_OLD); -} - -static void -unDredc(eChar c) -{ - - Dpeekrd = c; -} - -static eChar -Dredc(void) -{ - Char c; - - if ((c = Dpeekrd) != 0) { - Dpeekrd = 0; - return (c); - } - if (Dcp && (c = *Dcp++)) - return (c & (QUOTE | TRIM)); - if (*Dvp == 0) { - Dcp = 0; - return (DEOF); - } - Dcp = *Dvp++; - return (' '); -} - -static int gflag; - -static void -Dtestq(Char c) -{ - - if (cmap(c, QUOTES)) - gflag = 1; -} - -static void -inheredoc_cleanup(void *dummy) -{ - USE(dummy); - inheredoc = 0; -} - -/* - * Form a shell temporary file (in unit 0) from the words - * of the shell input up to EOF or a line the same as "term". - * Unit 0 should have been closed before this call. - */ -void -heredoc(Char *term) -{ - eChar c; - Char *Dv[2]; - struct Strbuf lbuf = Strbuf_INIT, mbuf = Strbuf_INIT; - Char obuf[BUFSIZE + 1]; -#define OBUF_END (obuf + sizeof(obuf) / sizeof (*obuf) - 1) - Char *lbp, *obp, *mbp; - Char **vp; - int quoted; - char *tmp; -#ifndef WINNT_NATIVE - struct timeval tv; - -again: -#endif /* WINNT_NATIVE */ - tmp = short2str(shtemp); -#ifndef O_CREAT -# define O_CREAT 0 - if (xcreat(tmp, 0600) < 0) - stderror(ERR_SYSTEM, tmp, strerror(errno)); -#endif - xclose(0); -#ifndef O_TEMPORARY -# define O_TEMPORARY 0 -#endif -#ifndef O_EXCL -# define O_EXCL 0 -#endif - if (xopen(tmp, O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY|O_LARGEFILE, 0600) == - -1) { - int oerrno = errno; -#ifndef WINNT_NATIVE - if (errno == EEXIST) { - if (unlink(tmp) == -1) { - (void) gettimeofday(&tv, NULL); - xfree(shtemp); - mbp = putn((((int)tv.tv_sec) ^ - ((int)tv.tv_usec) ^ ((int)getpid())) & 0x00ffffff); - shtemp = Strspl(STRtmpsh, mbp); - xfree(mbp); - } - goto again; - } -#endif /* WINNT_NATIVE */ - (void) unlink(tmp); - errno = oerrno; - stderror(ERR_SYSTEM, tmp, strerror(errno)); - } - (void) unlink(tmp); /* 0 0 inode! */ - Dv[0] = term; - Dv[1] = NULL; - gflag = 0; - trim(Dv); - rscan(Dv, Dtestq); - quoted = gflag; - obp = obuf; - obuf[BUFSIZE] = 0; - inheredoc = 1; - cleanup_push(&inheredoc, inheredoc_cleanup); -#ifdef WINNT_NATIVE - __dup_stdin = 1; -#endif /* WINNT_NATIVE */ -#ifdef O_TEXT - setmode(1, O_TEXT); -#endif -#ifdef O_BINARY - setmode(0, O_BINARY); -#endif - cleanup_push(&lbuf, Strbuf_cleanup); - cleanup_push(&mbuf, Strbuf_cleanup); - for (;;) { - Char **words; - - /* - * Read up a line - */ - lbuf.len = 0; - for (;;) { - c = readc(1); /* 1 -> Want EOF returns */ - if (c == CHAR_ERR || c == '\n') - break; - if ((c &= TRIM) != 0) - Strbuf_append1(&lbuf, (Char) c); - } - Strbuf_terminate(&lbuf); - - /* - * Check for EOF or compare to terminator -- before expansion - */ - if (c == CHAR_ERR || eq(lbuf.s, term)) - break; - - /* - * If term was quoted or -n just pass it on - */ - if (quoted || noexec) { - Strbuf_append1(&lbuf, '\n'); - Strbuf_terminate(&lbuf); - for (lbp = lbuf.s; (c = *lbp++) != 0;) { - *obp++ = (Char) c; - if (obp == OBUF_END) { - tmp = short2str(obuf); - (void) xwrite(0, tmp, strlen (tmp)); - obp = obuf; - } - } - continue; - } - - /* - * Term wasn't quoted so variable and then command expand the input - * line - */ - Dcp = lbuf.s; - Dvp = Dv + 1; - mbuf.len = 0; - for (;;) { - c = DgetC(DODOL); - if (c == DEOF) - break; - if ((c &= TRIM) == 0) - continue; - /* \ quotes \ $ ` here */ - if (c == '\\') { - c = DgetC(0); - if (!any("$\\`", c)) - unDgetC(c | QUOTE), c = '\\'; - else - c |= QUOTE; - } - Strbuf_append1(&mbuf, (Char) c); - } - Strbuf_terminate(&mbuf); - - /* - * If any ` in line do command substitution - */ - mbp = mbuf.s; - if (Strchr(mbp, '`') != NULL) { - /* - * 1 arg to dobackp causes substitution to be literal. Words are - * broken only at newlines so that all blanks and tabs are - * preserved. Blank lines (null words) are not discarded. - */ - words = dobackp(mbp, 1); - } - else - /* Setup trivial vector similar to return of dobackp */ - Dv[0] = mbp, Dv[1] = NULL, words = Dv; - - /* - * Resurrect the words from the command substitution each separated by - * a newline. Note that the last newline of a command substitution - * will have been discarded, but we put a newline after the last word - * because this represents the newline after the last input line! - */ - for (vp= words; *vp; vp++) { - for (mbp = *vp; *mbp; mbp++) { - *obp++ = *mbp & TRIM; - if (obp == OBUF_END) { - tmp = short2str(obuf); - (void) xwrite(0, tmp, strlen (tmp)); - obp = obuf; - } - } - *obp++ = '\n'; - if (obp == OBUF_END) { - tmp = short2str(obuf); - (void) xwrite(0, tmp, strlen (tmp)); - obp = obuf; - } - } - if (words != Dv) - blkfree(words); - } - *obp = 0; - tmp = short2str(obuf); - (void) xwrite(0, tmp, strlen (tmp)); - (void) lseek(0, (off_t) 0, L_SET); - cleanup_until(&inheredoc); -} |