From 52364258654418127d544d31b3c49b61019e2c7e Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Sun, 6 Oct 2013 21:35:27 +0100
Subject: users:18023: Add PIPEFAIL option
---
ChangeLog | 5 +++++
Doc/Zsh/options.yo | 14 ++++++++++++++
Src/jobs.c | 13 ++++++++++---
Src/options.c | 1 +
Src/zsh.h | 1 +
Test/E01options.ztst | 15 +++++++++++++++
6 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 1cf815eee..2613d5189 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-10-06 Peter Stephenson
+
+ * users/18023: Doc/Zsh/options.yo, Src/jobs.c, Src/options.c,
+ Src/zsh.h, Test/E01options.ztst: add PIPEFAIL option and test.
+
2013-10-05 Peter Stephenson
* Hang Pingtian: 31789: Src/hist.c: add history for
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index ec862321e..71bddd570 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -1683,6 +1683,20 @@ Sequences of digits indicating a numeric base such as the `tt(08)'
component in `tt(08#77)' are always interpreted as decimal, regardless
of leading zeroes.
)
+pindex(PIPE_FAIL)
+pindex(NO_PIPE_FAIL)
+pindex(PIPEFAIL)
+pindex(NOPIPEFAIL)
+cindex(exit status from pipeline)
+cindex(status, on exit from pipeline)
+cindex(pipeline, exit status from)
+itme(tt(PIPE_FAIL))(
+By default, when a pipeline exits the exit status recorded by the shell
+and returned by the shell variable tt($?) reflects that of the
+rightmost element of a pipeline. If this option is set, the exit status
+instead reflects the status of the rightmost element of the pipeline
+that was non-zero, or zero if all elements exited with zero status.
+)
pindex(SOURCE_TRACE)
pindex(NO_SOURCE_TRACE)
pindex(SOURCETRACE)
diff --git a/Src/jobs.c b/Src/jobs.c
index e1b24b2c9..b9d7a84cc 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -508,15 +508,22 @@ update_job(Job jn)
jn->stat |= (somestopped) ? STAT_CHANGED | STAT_STOPPED :
STAT_CHANGED | STAT_DONE;
if (job == thisjob && (jn->stat & STAT_DONE)) {
- int i;
+ int i, newlastval = 0;
Process p;
- for (p = jn->procs, i = 0; p && i < MAX_PIPESTATS; p = p->next, i++)
+ for (p = jn->procs, i = 0; p && i < MAX_PIPESTATS; p = p->next, i++) {
pipestats[i] = ((WIFSIGNALED(p->status)) ?
0200 | WTERMSIG(p->status) :
WEXITSTATUS(p->status));
- if ((jn->stat & STAT_CURSH) && i < MAX_PIPESTATS)
+ if (pipestats[i])
+ newlastval = pipestats[i];
+ }
+ if ((jn->stat & STAT_CURSH) && i < MAX_PIPESTATS) {
pipestats[i++] = lastval;
+ if (!lastval && isset(PIPEFAIL))
+ lastval = newlastval;
+ } else if (isset(PIPEFAIL))
+ lastval= newlastval;
numpipestats = i;
}
if (!inforeground &&
diff --git a/Src/options.c b/Src/options.c
index ad869b253..ce73d9901 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -205,6 +205,7 @@ static struct optname optns[] = {
{{NULL, "overstrike", 0}, OVERSTRIKE},
{{NULL, "pathdirs", OPT_EMULATE}, PATHDIRS},
{{NULL, "pathscript", OPT_EMULATE|OPT_BOURNE}, PATHSCRIPT},
+{{NULL, "pipefail", OPT_EMULATE}, PIPEFAIL},
{{NULL, "posixaliases", OPT_EMULATE|OPT_BOURNE}, POSIXALIASES},
{{NULL, "posixbuiltins", OPT_EMULATE|OPT_BOURNE}, POSIXBUILTINS},
{{NULL, "posixcd", OPT_EMULATE|OPT_BOURNE}, POSIXCD},
diff --git a/Src/zsh.h b/Src/zsh.h
index e6f0f65db..a46898d7d 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2121,6 +2121,7 @@ enum {
OVERSTRIKE,
PATHDIRS,
PATHSCRIPT,
+ PIPEFAIL,
POSIXALIASES,
POSIXBUILTINS,
POSIXCD,
diff --git a/Test/E01options.ztst b/Test/E01options.ztst
index bcb34c352..e00eb0e9c 100644
--- a/Test/E01options.ztst
+++ b/Test/E01options.ztst
@@ -1096,3 +1096,18 @@
0:IGNORE_CLOSE_BRACES option
>this is OK
>6
+
+ (setopt pipefail
+ true | true | true
+ print $?
+ true | false | true
+ print $?
+ exit 2 | false | true
+ print $?
+ false | exit 2 | true
+ print $?)
+0:PIPE_FAIL option
+>0
+>1
+>1
+>2
--
cgit 1.4.1