about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2014-10-02 16:15:10 +0100
committerPeter Stephenson <pws@zsh.org>2014-10-02 16:15:10 +0100
commitf16813792ecefce25f0cd19ad2806eb229b0799f (patch)
tree59b52dcf9f6d2a9a90edf250e1ef5a6a28a95dfc
parentdad5063a7c8f30654bc2f3f5d0cf6b53f79ec444 (diff)
downloadzsh-f16813792ecefce25f0cd19ad2806eb229b0799f.tar.gz
zsh-f16813792ecefce25f0cd19ad2806eb229b0799f.tar.xz
zsh-f16813792ecefce25f0cd19ad2806eb229b0799f.zip
33325: fix ksh autoloads with redirections on function definitions
-rw-r--r--ChangeLog5
-rw-r--r--Src/exec.c82
-rw-r--r--Test/A05execution.ztst13
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  <p.stephenson@samsung.com>
+
+	* 33325: Src/exec.c, Test/A05execution.ztst: fix ksh autoloads
+	with redirections on functiond definitions.
+
 2014-10-01  Barton E. Schaefer  <schaefer@zsh.org>
 
 	* 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
@@ -4574,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)
 {
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