summaryrefslogtreecommitdiff
path: root/Src/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/exec.c')
-rw-r--r--Src/exec.c65
1 files changed, 49 insertions, 16 deletions
diff --git a/Src/exec.c b/Src/exec.c
index 4576fc031..2558185c8 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -181,7 +181,15 @@ struct execstack *exstack;
/**/
mod_export Funcstack funcstack;
-#define execerr() if (!forked) { lastval = 1; goto done; } else _exit(1)
+#define execerr() \
+ do { \
+ if (!forked) { \
+ redir_err = lastval = 1; \
+ goto done; \
+ } else { \
+ _exit(1); \
+ } \
+ } while (0)
static int doneps4;
static char *STTYval;
@@ -2312,11 +2320,11 @@ execcmd(Estate state, int input, int output, int how, int last1)
struct multio *mfds[10];
char *text;
int save[10];
- int fil, dfil, is_cursh, type, do_exec = 0, i, htok = 0;
+ int fil, dfil, is_cursh, type, do_exec = 0, redir_err = 0, i, htok = 0;
int nullexec = 0, assign = 0, forked = 0;
int is_shfunc = 0, is_builtin = 0, is_exec = 0, use_defpath = 0;
/* Various flags to the command. */
- int cflags = 0, checked = 0, oautocont = -1;
+ int cflags = 0, orig_cflags = 0, checked = 0, oautocont = -1;
LinkList redir;
wordcode code;
Wordcode beg = state->pc, varspc;
@@ -2408,6 +2416,9 @@ execcmd(Estate state, int input, int output, int how, int last1)
checked = !(cflags & BINF_BUILTIN);
break;
}
+ orig_cflags |= cflags;
+ cflags &= ~BINF_BUILTIN & ~BINF_COMMAND;
+ cflags |= hn->flags;
if (!(hn->flags & BINF_PREFIX)) {
is_builtin = 1;
@@ -2417,8 +2428,6 @@ execcmd(Estate state, int input, int output, int how, int last1)
assign = (hn->flags & BINF_MAGICEQUALS);
break;
}
- cflags &= ~BINF_BUILTIN & ~BINF_COMMAND;
- cflags |= hn->flags;
checked = 0;
if ((cflags & BINF_COMMAND) && nextnode(firstnode(args))) {
/* check for options to command builtin */
@@ -2748,7 +2757,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
* A `fake exec' is possible if we have all the following conditions: *
* 1) last1 flag is 1. This indicates that the current shell will not *
* be needed after the current command. This is typically the case *
- * when when the command is the last stage in a subshell, or is the *
+ * when the command is the last stage in a subshell, or is the *
* last command after the option `-c'. *
* 2) We don't have any traps set. *
* 3) We don't have any files to delete. *
@@ -2999,10 +3008,11 @@ execcmd(Estate state, int input, int output, int how, int last1)
if (!checkclobberparam(fn))
fil = -1;
else if (fn->fd2 > 9 &&
- ((fdtable[fn->fd2] != FDT_UNUSED &&
- fdtable[fn->fd2] != FDT_EXTERNAL) ||
- fn->fd2 == coprocin ||
- fn->fd2 == coprocout)) {
+ (fn->fd2 > max_zsh_fd ||
+ (fdtable[fn->fd2] != FDT_UNUSED &&
+ fdtable[fn->fd2] != FDT_EXTERNAL) ||
+ fn->fd2 == coprocin ||
+ fn->fd2 == coprocout)) {
fil = -1;
errno = EBADF;
} else {
@@ -3069,7 +3079,6 @@ execcmd(Estate state, int input, int output, int how, int last1)
if (mfds[i] && mfds[i]->ct >= 2)
closemn(mfds, i);
- xtrerr = stderr;
if (nullexec) {
if (nullexec == 1) {
/*
@@ -3218,10 +3227,14 @@ execcmd(Estate state, int input, int output, int how, int last1)
_exit(1);
}
closem(FDT_INTERNAL);
- if (coprocin)
+ if (coprocin != -1) {
zclose(coprocin);
- if (coprocout)
+ coprocin = -1;
+ }
+ if (coprocout != -1) {
zclose(coprocout);
+ coprocout = -1;
+ }
#ifdef HAVE_GETRLIMIT
if (!forked)
setlimits(NULL);
@@ -3285,6 +3298,25 @@ execcmd(Estate state, int input, int output, int how, int last1)
fixfds(save);
done:
+ if (isset(POSIXBUILTINS) &&
+ (cflags & (BINF_PSPECIAL|BINF_EXEC)) &&
+ !(orig_cflags & BINF_COMMAND)) {
+ /*
+ * For POSIX-compatible behaviour with special
+ * builtins (including exec which we don't usually
+ * classify as a builtin) we treat all errors as fatal.
+ * The "command" builtin is not special so resets this behaviour.
+ */
+ if (redir_err || errflag) {
+ if (!isset(INTERACTIVE)) {
+ if (forked)
+ _exit(1);
+ else
+ exit(1);
+ }
+ errflag = 1;
+ }
+ }
if (newxtrerr) {
fil = fileno(newxtrerr);
fclose(newxtrerr);
@@ -4227,6 +4259,7 @@ execshfunc(Shfunc shf, LinkList args)
cmdsp = 0;
if ((osfc = sfcontext) == SFC_NONE)
sfcontext = SFC_DIRECT;
+ xtrerr = stderr;
doshfunc(shf, args, 0);
sfcontext = osfc;
free(cmdstack);
@@ -4365,7 +4398,7 @@ loadautofn(Shfunc shf, int fksh, int autol)
mod_export int
doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
{
- char **tab, **x, *oargv0;
+ char **pptab, **x, *oargv0;
int oldzoptind, oldlastval, oldoptcind, oldnumpipestats, ret;
int *oldpipestats = NULL;
char saveopts[OPT_SIZE], *oldscriptname = scriptname;
@@ -4399,7 +4432,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
starttrapscope();
- tab = pparams;
+ pptab = pparams;
if (!(flags & PM_UNDEFINED))
scriptname = dupstring(name);
oldzoptind = zoptind;
@@ -4515,7 +4548,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
zsfree(argzero);
argzero = oargv0;
}
- pparams = tab;
+ pparams = pptab;
optcind = oldoptcind;
zoptind = oldzoptind;
scriptname = oldscriptname;