[C++] Handle multi-word SHELL in $(shell)
diff --git a/fileutil.cc b/fileutil.cc
index 42e81a2..a2a0d09 100644
--- a/fileutil.cc
+++ b/fileutil.cc
@@ -32,6 +32,7 @@
 #include <unordered_map>
 
 #include "log.h"
+#include "strutil.h"
 
 bool Exists(StringPiece filename) {
   CHECK(filename.size() < PATH_MAX);
@@ -62,6 +63,13 @@
 int RunCommand(const string& shell, const string& cmd,
                RedirectStderr redirect_stderr,
                string* s) {
+  string cmd_escaped = cmd;
+  EscapeShell(&cmd_escaped);
+  string cmd_with_shell = shell + " -c \"" + cmd_escaped + "\"";
+  const char* argv[] = {
+    "/bin/sh", "-c", cmd_with_shell.c_str(), NULL
+  };
+
   int pipefd[2];
   if (pipe(pipefd) != 0)
     PERROR("pipe failed");
@@ -106,9 +114,6 @@
       PERROR("dup2 failed");
     close(pipefd[1]);
 
-    const char* argv[] = {
-      shell.c_str(), "-c", cmd.c_str(), NULL
-    };
     execvp(argv[0], const_cast<char**>(argv));
     PLOG("execvp for %s failed", argv[0]);
     kill(getppid(), SIGTERM);
diff --git a/ninja.cc b/ninja.cc
index c3b6a61..76d84f4 100644
--- a/ninja.cc
+++ b/ninja.cc
@@ -543,36 +543,6 @@
     return r;
   }
 
-  void EscapeShell(string* s) const {
-    if (s->find_first_of("$`\\\"") == string::npos)
-      return;
-    string r;
-    bool last_dollar = false;
-    for (char c : *s) {
-      switch (c) {
-        case '$':
-          if (last_dollar) {
-            r += c;
-            last_dollar = false;
-          } else {
-            r += '\\';
-            r += c;
-            last_dollar = true;
-          }
-          break;
-        case '`':
-        case '"':
-        case '\\':
-          r += '\\';
-          // fall through.
-        default:
-          r += c;
-          last_dollar = false;
-      }
-    }
-    s->swap(r);
-  }
-
   void EmitBuild(NinjaNode* nn, const string& rule_name,
                  bool use_local_pool, ostringstream* o) {
     const DepNode* node = nn->node;
diff --git a/strutil.cc b/strutil.cc
index bcef302..80a4b5b 100644
--- a/strutil.cc
+++ b/strutil.cc
@@ -521,3 +521,33 @@
   }
   return buf;
 }
+
+void EscapeShell(string* s) {
+  if (s->find_first_of("$`\\\"") == string::npos)
+    return;
+  string r;
+  bool last_dollar = false;
+  for (char c : *s) {
+    switch (c) {
+      case '$':
+        if (last_dollar) {
+          r += c;
+          last_dollar = false;
+        } else {
+          r += '\\';
+          r += c;
+          last_dollar = true;
+        }
+        break;
+      case '`':
+      case '"':
+      case '\\':
+        r += '\\';
+        // fall through.
+      default:
+        r += c;
+        last_dollar = false;
+    }
+  }
+  s->swap(r);
+}
diff --git a/strutil.h b/strutil.h
index 5938efb..12e46a5 100644
--- a/strutil.h
+++ b/strutil.h
@@ -142,4 +142,6 @@
 
 string EchoEscape(const string str);
 
+void EscapeShell(string* s);
+
 #endif  // STRUTIL_H_
diff --git a/testcase/shell_var_with_args.mk b/testcase/shell_var_with_args.mk
new file mode 100644
index 0000000..fd391f3
--- /dev/null
+++ b/testcase/shell_var_with_args.mk
@@ -0,0 +1,7 @@
+# TODO(go): Fix
+
+SHELL := PS4="cmd: " /bin/bash -x
+$(info $(shell echo foo))
+
+test:
+	@echo baz