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