summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2015-07-12 21:03:24 -0400
committerPaul Smith <psmith@gnu.org>2015-07-12 21:03:24 -0400
commit43181f1f8241c74f68d4ff85e567c418b128c569 (patch)
tree192c596b49846c8fa99235198865a01775c85d18
parentc18b23f7b249fb0ef17593b1641831fc05a56027 (diff)
[SV 28092] Preserve the exit status of the $(shell...) function.
Add a new variable .SHELLSTATUS which holds the exit status of the last-invoked shell function or != assignment. * NEWS, doc/make.texi: Document the change. * function.c (shell_completed, msdos_openpipe, func_shell_base): Add shell_completed() to handle the completion of the shell, by setting .SHELLSTATUS. Call it where needed. * job.c (child_handler): Call shell_completed(). * tests/scripts/functions/shell: Add tests for .SHELLSTATUS.
-rw-r--r--NEWS9
-rw-r--r--doc/make.texi9
-rw-r--r--function.c37
-rw-r--r--job.c7
-rw-r--r--tests/scripts/functions/shell19
-rw-r--r--variable.h2
6 files changed, 62 insertions, 21 deletions
diff --git a/NEWS b/NEWS
index 41b6518e..e98cb45c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,6 @@
GNU make NEWS -*-indented-text-*-
History of user-visible changes.
- 05 Oct 2014
+ 12 Jul 2015
See the end of this file for copyrights and conditions.
@@ -9,12 +9,17 @@ manual, which is contained in this distribution as the file doc/make.texi.
See the README file and the GNU make manual for instructions for
reporting bugs.
-Version 4.1.90 (05 Oct 2014)
+Version 4.1.90 (12 Jul 2015)
A complete list of bugs fixed in this version is available here:
http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=106&set=custom
+* New variable: $(.SHELLSTATUS) is set to the exit status of the last != or
+ $(shell ...) function invoked in this instance of make. This will be "0" if
+ successful or not "0" if not successful. The variable value is unset if no
+ != or $(shell ...) function has been invoked.
+
* VMS-specific changes:
* Perl test harness now works.
diff --git a/doc/make.texi b/doc/make.texi
index b0f5af73..86a1aebc 100644
--- a/doc/make.texi
+++ b/doc/make.texi
@@ -5669,7 +5669,7 @@ endif
@end example
The shell assignment operator @samp{!=} can be used to execute a
-program and set a variable to its output. This operator first
+shell script and set a variable to its output. This operator first
evaluates the right-hand side, then passes that result to the shell
for execution. If the result of the execution ends in a newline, that
one newline is removed; all other newlines are replaced by spaces.
@@ -5694,6 +5694,9 @@ hash := $(shell printf '\043')
var := $(shell find . -name "*.c")
@end example
+As with the @code{shell} function, the exit status of the just-invoked
+shell script is stored in the @code{.SHELLSTATUS} variable.
+
@node Appending, Override Directive, Setting, Using Variables
@section Appending More Text to Variables
@@ -8024,6 +8027,10 @@ implications of using the @code{shell} function within recursively
expanded variables vs.@: simply expanded variables (@pxref{Flavors, ,The
Two Flavors of Variables}).
+@vindex .SHELLSTATUS
+After the @code{shell} function or @samp{!=} assignment operator is
+used, its exit status is placed in the @code{.SHELLSTATUS} variable.
+
Here are some examples of the use of the @code{shell} function:
@example
diff --git a/function.c b/function.c
index 8bd2b5ce..02a25eb5 100644
--- a/function.c
+++ b/function.c
@@ -1450,7 +1450,22 @@ fold_newlines (char *buffer, unsigned int *length, int trim_newlines)
}
pid_t shell_function_pid = 0;
-int shell_function_completed;
+static int shell_function_completed;
+
+void
+shell_completed (int exit_code, int exit_sig)
+{
+ char buf[256];
+
+ shell_function_pid = 0;
+ if (exit_sig == 0 && exit_code == 127)
+ shell_function_completed = -1;
+ else
+ shell_function_completed = 1;
+
+ sprintf (buf, "%d", exit_code);
+ define_variable_cname (".SHELLSTATUS", buf, o_override, 0);
+}
#ifdef WINDOWS32
/*untested*/
@@ -1630,14 +1645,15 @@ msdos_openpipe (int* pipedes, int *pidp, char *text)
errno = EINTR;
else if (errno == 0)
errno = ENOMEM;
- shell_function_completed = -1;
+ if (fpipe)
+ pclose (fpipe);
+ shell_completed (127, 0);
}
else
{
pipedes[0] = fileno (fpipe);
*pidp = 42; /* Yes, the Meaning of Life, the Universe, and Everything! */
errno = e;
- shell_function_completed = 1;
}
return fpipe;
}
@@ -1696,7 +1712,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
#endif
return o;
}
-#endif
+#endif /* !__MSDOS__ */
/* Using a target environment for 'shell' loses in cases like:
export var = $(shell echo foobie)
@@ -1743,7 +1759,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
if (pipedes[0] < 0)
{
/* Open of the pipe failed, mark as failed execution. */
- shell_function_completed = -1;
+ shell_completed (127, 0);
perror_with_name (error_prefix, "pipe");
return o;
}
@@ -1824,7 +1840,10 @@ func_shell_base (char *o, char **argv, int trim_newlines)
/* Close the read side of the pipe. */
#ifdef __MSDOS__
if (fpipe)
- (void) pclose (fpipe);
+ {
+ int st = pclose (fpipe);
+ shell_completed (st, 0);
+ }
#else
(void) close (pipedes[0]);
#endif
@@ -1843,9 +1862,9 @@ func_shell_base (char *o, char **argv, int trim_newlines)
}
shell_function_pid = 0;
- /* The child_handler function will set shell_function_completed
- to 1 when the child dies normally, or to -1 if it
- dies with status 127, which is most likely an exec fail. */
+ /* shell_completed() will set shell_function_completed to 1 when the
+ child dies normally, or to -1 if it dies with status 127, which is
+ most likely an exec fail. */
if (shell_function_completed == -1)
{
diff --git a/job.c b/job.c
index 2ba0977e..244def03 100644
--- a/job.c
+++ b/job.c
@@ -558,7 +558,6 @@ child_handler (int sig UNUSED)
}
extern pid_t shell_function_pid;
-extern int shell_function_completed;
/* Reap all dead children, storing the returned status and the new command
state ('cs_finished') in the 'file' member of the 'struct child' for the
@@ -816,11 +815,7 @@ reap_children (int block, int err)
/* Check if this is the child of the 'shell' function. */
if (!remote && pid == shell_function_pid)
{
- /* It is. Leave an indicator for the 'shell' function. */
- if (exit_sig == 0 && exit_code == 127)
- shell_function_completed = -1;
- else
- shell_function_completed = 1;
+ shell_completed (exit_code, exit_sig);
break;
}
diff --git a/tests/scripts/functions/shell b/tests/scripts/functions/shell
index 723cd0ed..4702b096 100644
--- a/tests/scripts/functions/shell
+++ b/tests/scripts/functions/shell
@@ -4,11 +4,26 @@ $description = 'Test the $(shell ...) function.';
$details = '';
+# Test standard shell
+run_make_test('.PHONY: all
+OUT := $(shell echo hi)
+all: ; @echo $(OUT)
+ ','','hi');
# Test shells inside rules.
run_make_test('.PHONY: all
all: ; @echo $(shell echo hi)
-','','hi');
+ ','','hi');
+
+# Verify .SHELLSTATUS
+run_make_test('.PHONY: all
+PRE := $(.SHELLSTATUS)
+$(shell exit 0)
+OK := $(.SHELLSTATUS)
+$(shell exit 1)
+BAD := $(.SHELLSTATUS)
+all: ; @echo PRE=$(PRE) OK=$(OK) BAD=$(BAD)
+ ','','PRE= OK=0 BAD=1');
# Test unescaped comment characters in shells. Savannah bug #20513
@@ -27,6 +42,6 @@ run_make_test('
export HI = $(shell echo hi)
.PHONY: all
all: ; @echo $$HI
-','','hi');
+ ','','hi');
1;
diff --git a/variable.h b/variable.h
index fa2dbbd1..d8fb0d1f 100644
--- a/variable.h
+++ b/variable.h
@@ -134,7 +134,7 @@ char *patsubst_expand_pat (char *o, const char *text, const char *pattern,
const char *replace_percent);
char *patsubst_expand (char *o, const char *text, char *pattern, char *replace);
char *func_shell_base (char *o, char **argv, int trim_newlines);
-
+void shell_completed (int exit_code, int exit_sig);
/* expand.c */
char *recursively_expand_for_file (struct variable *v, struct file *file);