zsh-users
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: zsh-users@zsh.org
Subject: Re: No pipefail option?
Date: Sat, 5 Oct 2013 22:31:59 +0100	[thread overview]
Message-ID: <20131005223159.25fea6a0@pws-pc.ntlworld.com> (raw)
In-Reply-To: <CADv1Z=pM7H4Xg9+GyWd4zw0cv0mXfbJvqip6vc7e_yrXRN=1sg@mail.gmail.com>

On Fri, 4 Oct 2013 08:59:49 -0700
Shawn Halpenny <paxunix@gmail.com> wrote:
> It seems like it would be a good bash-compatibility option to have
> available.  I know we can check $pipestatus, but often I simply want to
> abort the script if any command in the pipeline failed without having to do
> an explicit check (similarly to how the errexit option works).  Explicit
> checks too easily get forgotten or overlooked or even just implemented
> incorrectly.

It's not impossible it's this simple.

Indeed, if $pipestatus is working as advertised, it really ought to be
this simple...

diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index ec86232..71bddd5 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 e1b24b2..b9d7a84 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 ad869b2..ce73d99 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 e6f0f65..a46898d 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 bcb34c3..e00eb0e 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

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


      reply	other threads:[~2013-10-05 21:38 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-04 15:59 Shawn Halpenny
2013-10-05 21:31 ` Peter Stephenson [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20131005223159.25fea6a0@pws-pc.ntlworld.com \
    --to=p.w.stephenson@ntlworld.com \
    --cc=zsh-users@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).