aboutsummaryrefslogtreecommitdiff
path: root/src/nix-build
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix-build')
-rw-r--r--src/nix-build/nix-build.cc38
1 files changed, 26 insertions, 12 deletions
diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc
index 2895c5e3c..e62c4f6b1 100644
--- a/src/nix-build/nix-build.cc
+++ b/src/nix-build/nix-build.cc
@@ -34,13 +34,14 @@ extern char * * environ __attribute__((weak));
*/
static std::vector<std::string> shellwords(const std::string & s)
{
- std::regex whitespace("^(\\s+).*");
+ std::regex whitespace("^\\s+");
auto begin = s.cbegin();
std::vector<std::string> res;
std::string cur;
enum state {
sBegin,
- sQuote
+ sSingleQuote,
+ sDoubleQuote
};
state st = sBegin;
auto it = begin;
@@ -50,26 +51,39 @@ static std::vector<std::string> shellwords(const std::string & s)
if (regex_search(it, s.cend(), match, whitespace)) {
cur.append(begin, it);
res.push_back(cur);
- cur.clear();
- it = match[1].second;
+ it = match[0].second;
+ if (it == s.cend()) return res;
begin = it;
+ cur.clear();
}
}
switch (*it) {
+ case '\'':
+ if (st != sDoubleQuote) {
+ cur.append(begin, it);
+ begin = it + 1;
+ st = st == sBegin ? sSingleQuote : sBegin;
+ }
+ break;
case '"':
- cur.append(begin, it);
- begin = it + 1;
- st = st == sBegin ? sQuote : sBegin;
+ if (st != sSingleQuote) {
+ cur.append(begin, it);
+ begin = it + 1;
+ st = st == sBegin ? sDoubleQuote : sBegin;
+ }
break;
case '\\':
- /* perl shellwords mostly just treats the next char as part of the string with no special processing */
- cur.append(begin, it);
- begin = ++it;
+ if (st != sSingleQuote) {
+ /* perl shellwords mostly just treats the next char as part of the string with no special processing */
+ cur.append(begin, it);
+ begin = ++it;
+ }
break;
}
}
+ if (st != sBegin) throw Error("unterminated quote in shebang line");
cur.append(begin, it);
- if (!cur.empty()) res.push_back(cur);
+ res.push_back(cur);
return res;
}
@@ -128,7 +142,7 @@ static void main_nix_build(int argc, char * * argv)
for (auto line : lines) {
line = chomp(line);
std::smatch match;
- if (std::regex_match(line, match, std::regex("^#!\\s*nix-shell (.*)$")))
+ if (std::regex_match(line, match, std::regex("^#!\\s*nix-shell\\s+(.*)$")))
for (const auto & word : shellwords(match[1].str()))
args.push_back(word);
}