diff options
author | Axel Beckert <abe@deuxchevaux.org> | 2014-10-08 01:29:12 +0200 |
---|---|---|
committer | Axel Beckert <abe@deuxchevaux.org> | 2014-10-08 01:29:12 +0200 |
commit | 1c3f90e3af0c3d6c8e946653169287baf5814ad4 (patch) | |
tree | 9b15e9ad8157bd8f9f697f6dc4e59146b6833c59 /Src/exec.c | |
parent | 1ffb184b46edd34d389af4e016abcaafec454d44 (diff) | |
parent | 9982ab6fb5266298c056326ed265fc8560202603 (diff) | |
download | zsh-1c3f90e3af0c3d6c8e946653169287baf5814ad4.tar.gz zsh-1c3f90e3af0c3d6c8e946653169287baf5814ad4.zip |
Merge commit '9982ab6fb5266298c056326ed265fc8560202603' into debian
This is exactly one commit after the zsh-5.0.7 and adds one missing
(and not unimportant) changelog entry for the 5.0.7 release.
Diffstat (limited to 'Src/exec.c')
-rw-r--r-- | Src/exec.c | 187 |
1 files changed, 166 insertions, 21 deletions
diff --git a/Src/exec.c b/Src/exec.c index 5ad957f98..d0fadd69a 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -198,7 +198,8 @@ static char *blank_env[] = { NULL }; /* Execution functions. */ static int (*execfuncs[WC_COUNT-WC_CURSH]) _((Estate, int)) = { - execcursh, exectime, execfuncdef, execfor, execselect, + execcursh, exectime, NULL /* execfuncdef handled specially */, + execfor, execselect, execwhile, execrepeat, execcase, execif, execcond, execarith, execautofn, exectry }; @@ -1005,6 +1006,8 @@ entersubsh(int flags) signal_default(SIGTERM); if (!(sigtrapped[SIGINT] & ZSIG_IGNORED)) signal_default(SIGINT); + if (!(sigtrapped[SIGPIPE])) + signal_default(SIGPIPE); } if (!(sigtrapped[SIGQUIT] & ZSIG_IGNORED)) signal_default(SIGQUIT); @@ -1116,8 +1119,11 @@ execsimple(Estate state) fflush(xtrerr); } lv = (errflag ? errflag : cmdoutval); - } else + } else if (code == WC_FUNCDEF) { + lv = execfuncdef(state, NULL); + } else { lv = (execfuncs[code - WC_CURSH])(state, 0); + } thisjob = otj; @@ -2783,6 +2789,58 @@ execcmd(Estate state, int input, int output, int how, int last1) errflag = 1; } + if (type == WC_FUNCDEF) { + /* + * The first word of a function definition is a list of + * names. If this is empty, we're doing an anonymous function: + * in that case redirections are handled normally. + * If not, it's a function definition: then we don't do + * redirections here but pass in the list of redirections to + * be stored for recall with the function. + */ + if (*state->pc != 0) { + /* Nonymous, don't do redirections here */ + redir = NULL; + } + } else if (is_shfunc || type == WC_AUTOFN) { + Shfunc shf; + if (is_shfunc) + shf = (Shfunc)hn; + else { + shf = loadautofn(state->prog->shf, 1, 0); + if (shf) + state->prog->shf = shf; + else { + /* + * This doesn't set errflag, so just return now. + */ + lastval = 1; + if (oautocont >= 0) + opts[AUTOCONTINUE] = oautocont; + return; + } + } + /* + * A function definition may have a list of additional + * redirections to apply, so retrieve it. + */ + if (shf->redir) { + struct estate s; + LinkList redir2; + + s.prog = shf->redir; + s.pc = shf->redir->prog; + s.strs = shf->redir->strs; + redir2 = ecgetredirs(&s); + if (!redir) + redir = redir2; + else { + while (nonempty(redir2)) + addlinknode(redir, ugetnode(redir2)); + } + } + } + if (errflag) { lastval = 1; if (oautocont >= 0) @@ -3050,7 +3108,7 @@ execcmd(Estate state, int input, int output, int how, int last1) break; case REDIR_CLOSE: if (fn->varid) { - char *s = fn->varid; + char *s = fn->varid, *t; struct value vbuf; Value v; int bad = 0; @@ -3060,13 +3118,25 @@ execcmd(Estate state, int input, int output, int how, int last1) } else if (v->pm->node.flags & PM_READONLY) { bad = 2; } else { - fn->fd1 = (int)getintvalue(v); + s = getstrvalue(v); if (errflag) bad = 1; - else if (fn->fd1 <= max_zsh_fd) { - if (fn->fd1 >= 10 && - fdtable[fn->fd1] == FDT_INTERNAL) - bad = 3; + else { + fn->fd1 = zstrtol(s, &t, 0); + if (s == t) + bad = 1; + else if (*t) { + /* Check for base#number format */ + if (*t == '#' && *s != '0') + fn->fd1 = zstrtol(s = t+1, &t, fn->fd1); + if (s == t || *t) + bad = 1; + } + if (!bad && fn->fd1 <= max_zsh_fd) { + if (fn->fd1 >= 10 && + fdtable[fn->fd1] == FDT_INTERNAL) + bad = 3; + } } } if (bad) { @@ -3131,7 +3201,7 @@ execcmd(Estate state, int input, int output, int how, int last1) fil = movefd(dup(fd)); } if (fil == -1) { - char fdstr[4]; + char fdstr[DIGBUFSIZE]; closemnodes(mfds); fixfds(save); @@ -3226,10 +3296,44 @@ execcmd(Estate state, int input, int output, int how, int last1) flags |= ESUB_REVERTPGRP; entersubsh(flags); } - if (type >= WC_CURSH) { + if (type == WC_FUNCDEF) { + Eprog redir_prog; + if (!redir && wc_code(*beg) == WC_REDIR) { + /* + * We're not using a redirection from the currently + * parsed environment, which is what we'd do for an + * anonymous function, but there are redirections we + * should store with the new function. + */ + struct estate s; + + s.prog = state->prog; + s.pc = beg; + s.strs = state->prog->strs; + + /* + * The copy uses the wordcode parsing area, so save and + * restore state. + */ + lexsave(); + redir_prog = eccopyredirs(&s); + lexrestore(); + } else + redir_prog = NULL; + + lastval = execfuncdef(state, redir_prog); + } + else if (type >= WC_CURSH) { if (last1 == 1) do_exec = 1; - lastval = (execfuncs[type - WC_CURSH])(state, do_exec); + if (type == WC_AUTOFN) { + /* + * We pre-loaded this to get any redirs. + * So we execuate a simplified function here. + */ + lastval = execautofn_basic(state, do_exec); + } else + lastval = (execfuncs[type - WC_CURSH])(state, do_exec); } else if (is_builtin || is_shfunc) { LinkList restorelist = 0, removelist = 0; /* builtin or shell function */ @@ -3569,8 +3673,11 @@ closem(int how) for (i = 10; i <= max_zsh_fd; i++) if (fdtable[i] != FDT_UNUSED && - (how == FDT_UNUSED || fdtable[i] == how)) + (how == FDT_UNUSED || fdtable[i] == how)) { + if (i == SHTTY) + SHTTY = -1; zclose(i); + } } /* convert here document into a here string */ @@ -4220,11 +4327,12 @@ exectime(Estate state, UNUSED(int do_exec)) /**/ static int -execfuncdef(Estate state, UNUSED(int do_exec)) +execfuncdef(Estate state, Eprog redir_prog) { Shfunc shf; char *s = NULL; int signum, nprg, sbeg, nstrs, npats, len, plen, i, htok = 0, ret = 0; + int nfunc = 0; Wordcode beg = state->pc, end; Eprog prog; Patprog *pp; @@ -4249,6 +4357,8 @@ execfuncdef(Estate state, UNUSED(int do_exec)) } } + DPUTS(!names && redir_prog, + "Passing redirection to anon function definition."); while (!names || (s = (char *) ugetnode(names))) { if (!names) { prog = (Eprog) zhalloc(sizeof(*prog)); @@ -4290,6 +4400,15 @@ execfuncdef(Estate state, UNUSED(int do_exec)) shf->node.flags = 0; shf->filename = ztrdup(scriptfilename); shf->lineno = lineno; + /* + * redir_prog is permanently allocated --- but if + * this function has multiple names we need an additional + * one. + */ + if (nfunc++ && redir_prog) + shf->redir = dupeprog(redir_prog, 0); + else + shf->redir = redir_prog; shfunc_set_sticky(shf); if (!names) { @@ -4320,6 +4439,8 @@ execfuncdef(Estate state, UNUSED(int do_exec)) ret = lastval; freeeprog(shf->funcdef); + if (shf->redir) /* shouldn't be */ + freeeprog(shf->redir); zsfree(shf->filename); zfree(shf, sizeof(*shf)); break; @@ -4343,6 +4464,10 @@ execfuncdef(Estate state, UNUSED(int do_exec)) shfunctab->addnode(shfunctab, ztrdup(s), shf); } } + if (!nfunc && redir_prog) { + /* For completeness, shouldn't happen */ + freeeprog(redir_prog); + } state->pc = end; return ret; } @@ -4439,21 +4564,28 @@ execshfunc(Shfunc shf, LinkList args) deletefilelist(last_file_list, 0); } -/* Function to execute the special type of command that represents an * - * autoloaded shell function. The command structure tells us which * - * function it is. This function is actually called as part of the * - * execution of the autoloaded function itself, so when the function * - * has been autoloaded, its list is just run with no frills. */ +/* + * Function to execute the special type of command that represents an + * autoloaded shell function. The command structure tells us which + * function it is. This function is actually called as part of the + * execution of the autoloaded function itself, so when the function + * has been autoloaded, its list is just run with no frills. + * + * There are two cases because if we are doing all-singing, all-dancing + * non-simple code we load the shell function early in execcmd() (the + * action also present in the non-basic version) to check if + * there are redirections that need to be handled at that point. + * Then we call execautofn_basic() to do the rest. + */ /**/ static int -execautofn(Estate state, UNUSED(int do_exec)) +execautofn_basic(Estate state, UNUSED(int do_exec)) { Shfunc shf; char *oldscriptname, *oldscriptfilename; - if (!(shf = loadautofn(state->prog->shf, 1, 0))) - return 1; + shf = state->prog->shf; /* * Probably we didn't know the filename where this function was @@ -4473,6 +4605,19 @@ execautofn(Estate state, UNUSED(int do_exec)) } /**/ +static int +execautofn(Estate state, UNUSED(int do_exec)) +{ + Shfunc shf; + + if (!(shf = loadautofn(state->prog->shf, 1, 0))) + return 1; + + state->prog->shf = shf; + return execautofn_basic(state, 0); +} + +/**/ Shfunc loadautofn(Shfunc shf, int fksh, int autol) { |