From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 138 invoked by alias); 5 Oct 2013 21:38:14 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 18023 Received: (qmail 25719 invoked from network); 5 Oct 2013 21:37:59 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:subject:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; bh=mhaHRTF2saLybT0ezJb17VxD9ESIlDPK4weAutzFWeE=; b=beB6mgc5RGHO0HnbIkbHw6rZBzweTJIZ4ySYotFlSQo9hZ75rgT20inGzmTGZGw8gN m1CsYhvLBIPt1LCdTgqKGz4M0Ol+kclo9g/nn8dY/ZpbTU/NMl5ltThABCHe/NmfXIYv 1xBPYhvY92UrZA5lfjQm4DE++pzvGW9zkVPFSKUryVg3it9HcJAzCluPFrvYsmJ/UXiC 3r9yi/9IlNxbuBkDD2860Vu17UxUp70uwhQE+mBzKbAggSiyTyfI5edwFUksq4XeJCAI H7YQ0oXoAz4ZNUJyR+NqHSn1zqCxv2qcGYbCf99BjTHf0LmquyMQaWRz4ciWDaBrAdcU n47Q== X-Gm-Message-State: ALoCoQlcSiXi/a066fqK/YDHoiF5mjw8lN/fsL/CRZEW1bsWe26cAhHpB6wCqTRt+tiH8jK7sgGK X-Received: by 10.194.24.168 with SMTP id v8mr18212811wjf.28.1381008722478; Sat, 05 Oct 2013 14:32:02 -0700 (PDT) X-ProxyUser-IP: 86.6.157.246 Date: Sat, 5 Oct 2013 22:31:59 +0100 From: Peter Stephenson To: zsh-users@zsh.org Subject: Re: No pipefail option? Message-ID: <20131005223159.25fea6a0@pws-pc.ntlworld.com> In-Reply-To: References: X-Mailer: Claws Mail 3.8.0 (GTK+ 2.24.7; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Fri, 4 Oct 2013 08:59:49 -0700 Shawn Halpenny 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 Web page now at http://homepage.ntlworld.com/p.w.stephenson/