ash: implement set -o pipefail (conditional on bash compat). +39 bytes
authorMichael Abbott <michael@araneidae.co.uk>
Fri, 4 Dec 2009 22:03:29 +0000 (23:03 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 4 Dec 2009 22:03:29 +0000 (23:03 +0100)
Signed-off-by: Michael Abbott <michael@araneidae.co.uk>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c

index 65d41cc5b3423fdab98c937d1b7c1a38f47392fc..e7cf7975f412f6fe516911969c7ad1b033f920eb 100644 (file)
@@ -101,6 +101,9 @@ static const char *const optletters_optnames[] = {
        "b"   "notify",
        "u"   "nounset",
        "\0"  "vi",
+#if ENABLE_ASH_BASH_COMPAT
+       "\0"  "pipefail"
+#endif
 #if DEBUG
        ,"\0"  "nolog"
        ,"\0"  "debug"
@@ -178,9 +181,14 @@ struct globals_misc {
 #define bflag optlist[11]
 #define uflag optlist[12]
 #define viflag optlist[13]
+#if ENABLE_ASH_BASH_COMPAT
+# define pipefail optlist[14]
+#else
+# define pipefail 0
+#endif
 #if DEBUG
-#define nolog optlist[14]
-#define debug optlist[15]
+# define nolog optlist[14 + ENABLE_ASH_BASH_COMPAT]
+# define debug optlist[15 + ENABLE_ASH_BASH_COMPAT]
 #endif
 
        /* trap handler commands */
@@ -3999,13 +4007,23 @@ jobscmd(int argc UNUSED_PARAM, char **argv)
 }
 #endif /* JOBS */
 
+/* Called only on finished or stopped jobs (no members are running) */
 static int
 getstatus(struct job *job)
 {
        int status;
        int retval;
+       struct procstat *ps;
+
+       /* Fetch last member's status */
+       ps = job->ps + job->nprocs - 1;
+       status = ps->ps_status;
+       if (pipefail) {
+               /* "set -o pipefail" mode: use last _nonzero_ status */
+               while (status == 0 && --ps >= job->ps)
+                       status = ps->ps_status;
+       }
 
-       status = job->ps[job->nprocs - 1].ps_status;
        retval = WEXITSTATUS(status);
        if (!WIFEXITED(status)) {
 #if JOBS