From f16813792ecefce25f0cd19ad2806eb229b0799f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 2 Oct 2014 16:15:10 +0100 Subject: 33325: fix ksh autoloads with redirections on function definitions --- ChangeLog | 5 +++ Src/exec.c | 82 ++++++++++++++++++++++++++++++++++++++------------ Test/A05execution.ztst | 13 ++++++++ 3 files changed, 81 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8f6e73736..fd17e025a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-10-02 Peter Stephenson + + * 33325: Src/exec.c, Test/A05execution.ztst: fix ksh autoloads + with redirections on functiond definitions. + 2014-10-01 Barton E. Schaefer * 33319: Doc/Zsh/grammar.yo: fix parens in example from 33312 diff --git a/Src/exec.c b/Src/exec.c index 10f71dab6..a5452e56e 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -2789,13 +2789,6 @@ execcmd(Estate state, int input, int output, int how, int last1) errflag = 1; } - if (errflag) { - lastval = 1; - if (oautocont >= 0) - opts[AUTOCONTINUE] = oautocont; - return; - } - if (type == WC_FUNCDEF) { /* * The first word of a function definition is a list of @@ -2809,8 +2802,24 @@ execcmd(Estate state, int input, int output, int how, int last1) /* Nonymous, don't do redirections here */ redir = NULL; } - } else if (is_shfunc) { - Shfunc shf = (Shfunc)hn; + } 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. @@ -2832,6 +2841,13 @@ execcmd(Estate state, int input, int output, int how, int last1) } } + if (errflag) { + lastval = 1; + if (oautocont >= 0) + opts[AUTOCONTINUE] = oautocont; + return; + } + if (type == WC_SIMPLE && !nullexec) { char *s; char trycd = (isset(AUTOCD) && isset(SHINSTDIN) && @@ -3306,10 +3322,18 @@ execcmd(Estate state, int input, int output, int how, int last1) redir_prog = NULL; lastval = execfuncdef(state, redir_prog); - } else if (type >= WC_CURSH) { + } + 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 */ @@ -4540,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 @@ -4573,6 +4604,19 @@ execautofn(Estate state, UNUSED(int do_exec)) return lastval; } +/**/ +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) diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst index df6d7bc06..8d256ff84 100644 --- a/Test/A05execution.ztst +++ b/Test/A05execution.ztst @@ -216,3 +216,16 @@ F:This similar test was triggering a reproducible failure with pipestatus. >done F:This test checks for a file descriptor leak that could cause the left F:side of a pipe to block on write after the right side has exited + + print "autoload_redir() { print Autoloaded ksh style; } >autoload.log" >autoload_redir + autoload -Uk autoload_redir + autoload_redir + print No output yet + cat autoload.log + functions autoload_redir +0: +>No output yet +>Autoloaded ksh style +>autoload_redir () { +> print Autoloaded ksh style +>} > autoload.log -- cgit 1.4.1