[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.
This commit is contained in:
Paul Smith 2015-07-12 21:03:24 -04:00
parent c18b23f7b2
commit 43181f1f82
6 changed files with 62 additions and 21 deletions

9
NEWS
View File

@ -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.

View File

@ -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

View File

@ -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)
{

7
job.c
View File

@ -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;
}

View File

@ -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;

View File

@ -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);