aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--exec.cc7
-rw-r--r--fileutil.cc25
-rw-r--r--fileutil.h4
-rw-r--r--fileutil_bench.cc10
-rw-r--r--func.cc12
-rw-r--r--func.h1
-rw-r--r--ninja.cc1
-rw-r--r--regen.cc4
8 files changed, 42 insertions, 22 deletions
diff --git a/exec.cc b/exec.cc
index 6065169..1569519 100644
--- a/exec.cc
+++ b/exec.cc
@@ -46,7 +46,8 @@ class Executor {
explicit Executor(Evaluator* ev)
: ce_(ev),
num_commands_(0) {
- shell_ = ev->GetShellAndFlag();
+ shell_ = ev->GetShell();
+ shellflag_ = ev->GetShellFlag();
}
double ExecNode(DepNode* n, DepNode* needed_by) {
@@ -106,7 +107,8 @@ class Executor {
}
if (!g_flags.is_dry_run) {
string out;
- int result = RunCommand(shell_, command->cmd.c_str(),
+ int result = RunCommand(shell_, shellflag_,
+ command->cmd.c_str(),
RedirectStderr::STDOUT,
&out);
printf("%s", out.c_str());
@@ -136,6 +138,7 @@ class Executor {
CommandEvaluator ce_;
unordered_map<Symbol, double> done_;
string shell_;
+ string shellflag_;
uint64_t num_commands_;
};
diff --git a/fileutil.cc b/fileutil.cc
index 0d3c2d6..4cf653b 100644
--- a/fileutil.cc
+++ b/fileutil.cc
@@ -60,15 +60,24 @@ double GetTimestamp(StringPiece filename) {
return GetTimestampFromStat(st);
}
-int RunCommand(const string& shell, const string& cmd,
- RedirectStderr redirect_stderr,
+int RunCommand(const string& shell, const string& shellflag,
+ const string& cmd, RedirectStderr redirect_stderr,
string* s) {
- string cmd_escaped = cmd;
- EscapeShell(&cmd_escaped);
- string cmd_with_shell = shell + " \"" + cmd_escaped + "\"";
- const char* argv[] = {
- "/bin/sh", "-c", cmd_with_shell.c_str(), NULL
- };
+ const char* argv[] = { NULL, NULL, NULL, NULL };
+ string cmd_with_shell;
+ if (shell[0] != '/' || shell.find_first_of(" $") != string::npos) {
+ string cmd_escaped = cmd;
+ EscapeShell(&cmd_escaped);
+ cmd_with_shell = shell + " " + shellflag + " \"" + cmd_escaped + "\"";
+ argv[0] = "/bin/sh";
+ argv[1] = "-c";
+ argv[2] = cmd_with_shell.c_str();
+ } else {
+ // If the shell isn't complicated, we don't need to wrap in /bin/sh
+ argv[0] = shell.c_str();
+ argv[1] = shellflag.c_str();
+ argv[2] = cmd.c_str();
+ }
int pipefd[2];
if (pipe(pipefd) != 0)
diff --git a/fileutil.h b/fileutil.h
index 7cc3c8e..264d9e1 100644
--- a/fileutil.h
+++ b/fileutil.h
@@ -36,8 +36,8 @@ enum struct RedirectStderr {
DEV_NULL,
};
-int RunCommand(const string& shell, const string& cmd,
- RedirectStderr redirect_stderr,
+int RunCommand(const string& shell, const string& shellflag,
+ const string& cmd, RedirectStderr redirect_stderr,
string* out);
void GetExecutablePath(string* path);
diff --git a/fileutil_bench.cc b/fileutil_bench.cc
index dc07d9a..4b1f033 100644
--- a/fileutil_bench.cc
+++ b/fileutil_bench.cc
@@ -17,21 +17,23 @@
#include <cstdio>
static void BM_RunCommand(benchmark::State& state) {
- std::string shell = "/bin/bash -c";
+ std::string shell = "/bin/bash";
+ std::string shellflag = "-c";
std::string cmd = "echo $((1+3))";
while (state.KeepRunning()) {
std::string result;
- RunCommand(shell, cmd, RedirectStderr::NONE, &result);
+ RunCommand(shell, shellflag, cmd, RedirectStderr::NONE, &result);
}
}
BENCHMARK(BM_RunCommand);
static void BM_RunCommand_ComplexShell(benchmark::State& state) {
- std::string shell = "/bin/bash -c";
+ std::string shell = "/bin/bash ";
+ std::string shellflag = "-c";
std::string cmd = "echo $((1+3))";
while (state.KeepRunning()) {
std::string result;
- RunCommand(shell, cmd, RedirectStderr::NONE, &result);
+ RunCommand(shell, shellflag, cmd, RedirectStderr::NONE, &result);
}
}
BENCHMARK(BM_RunCommand_ComplexShell);
diff --git a/func.cc b/func.cc
index 623e56e..7915aea 100644
--- a/func.cc
+++ b/func.cc
@@ -491,8 +491,8 @@ static bool HasNoIoInShellScript(const string& cmd) {
return false;
}
-static void ShellFuncImpl(const string& shell, const string& cmd,
- string* s, FindCommand** fc) {
+static void ShellFuncImpl(const string& shell, const string& shellflag,
+ const string& cmd, string* s, FindCommand** fc) {
LOG("ShellFunc: %s", cmd.c_str());
#ifdef TEST_FIND_EMULATOR
@@ -517,7 +517,7 @@ static void ShellFuncImpl(const string& shell, const string& cmd,
}
COLLECT_STATS_WITH_SLOW_REPORT("func shell time", cmd.c_str());
- RunCommand(shell, cmd, RedirectStderr::NONE, s);
+ RunCommand(shell, shellflag, cmd, RedirectStderr::NONE, s);
FormatForCommandSubstitution(s);
#ifdef TEST_FIND_EMULATOR
@@ -564,14 +564,16 @@ void ShellFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
return;
}
- const string&& shell = ev->GetShellAndFlag();
+ const string&& shell = ev->GetShell();
+ const string&& shellflag = ev->GetShellFlag();
string out;
FindCommand* fc = NULL;
- ShellFuncImpl(shell, cmd, &out, &fc);
+ ShellFuncImpl(shell, shellflag, cmd, &out, &fc);
if (ShouldStoreCommandResult(cmd)) {
CommandResult* cr = new CommandResult();
cr->shell = shell;
+ cr->shellflag = shellflag;
cr->cmd = cmd;
cr->find.reset(fc);
cr->result = out;
diff --git a/func.h b/func.h
index e78deb7..82e821c 100644
--- a/func.h
+++ b/func.h
@@ -43,6 +43,7 @@ struct FindCommand;
struct CommandResult {
string shell;
+ string shellflag;
string cmd;
unique_ptr<FindCommand> find;
string result;
diff --git a/ninja.cc b/ninja.cc
index 90fe404..e2bc9cd 100644
--- a/ninja.cc
+++ b/ninja.cc
@@ -737,6 +737,7 @@ class NinjaGenerator {
DumpInt(fp, crs.size());
for (CommandResult* cr : crs) {
DumpString(fp, cr->shell);
+ DumpString(fp, cr->shellflag);
DumpString(fp, cr->cmd);
DumpString(fp, cr->result);
if (!cr->find.get()) {
diff --git a/regen.cc b/regen.cc
index f5ed50a..a322691 100644
--- a/regen.cc
+++ b/regen.cc
@@ -53,6 +53,7 @@ class StampChecker {
struct ShellResult {
string shell;
+ string shellflag;
string cmd;
string result;
vector<string> missing_dirs;
@@ -232,6 +233,7 @@ class StampChecker {
ShellResult* sr = new ShellResult;
commands_.push_back(sr);
LOAD_STRING(fp, &sr->shell);
+ LOAD_STRING(fp, &sr->shellflag);
LOAD_STRING(fp, &sr->cmd);
LOAD_STRING(fp, &sr->result);
sr->has_condition = LOAD_INT(fp);
@@ -340,7 +342,7 @@ class StampChecker {
COLLECT_STATS_WITH_SLOW_REPORT("shell time (regen)", sr->cmd.c_str());
string result;
- RunCommand(sr->shell, sr->cmd, RedirectStderr::DEV_NULL, &result);
+ RunCommand(sr->shell, sr->shellflag, sr->cmd, RedirectStderr::DEV_NULL, &result);
FormatForCommandSubstitution(&result);
if (sr->result != result) {
if (g_flags.dump_kati_stamp) {