aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShinichiro Hamaji <shinichiro.hamaji@gmail.com>2016-02-18 17:20:08 +0900
committerShinichiro Hamaji <shinichiro.hamaji@gmail.com>2016-02-18 17:21:26 +0900
commit348a960f31d42c63ec6fff68a27c5b161b59a89f (patch)
tree867a4d5127635d88c9e9399ea7d774dd9d6f2340
parent3deff5bf54db9c5d36b775beffadbae33381d1b1 (diff)
downloadandroid_build_kati-348a960f31d42c63ec6fff68a27c5b161b59a89f.tar.gz
android_build_kati-348a960f31d42c63ec6fff68a27c5b161b59a89f.tar.bz2
android_build_kati-348a960f31d42c63ec6fff68a27c5b161b59a89f.zip
[C++] Handle multi-word SHELL in $(shell)
-rw-r--r--fileutil.cc11
-rw-r--r--ninja.cc30
-rw-r--r--strutil.cc30
-rw-r--r--strutil.h2
-rw-r--r--testcase/shell_var_with_args.mk7
5 files changed, 47 insertions, 33 deletions
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 @@ double GetTimestamp(StringPiece filename) {
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 @@ int RunCommand(const string& shell, const string& cmd,
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 @@ class NinjaGenerator {
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 @@ string EchoEscape(const string str) {
}
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 ConcatDir(StringPiece b, StringPiece n);
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