diff --git a/src/libutil/args.cc b/src/libutil/args.cc index 2b72079f2..d17a1e7a9 100644 --- a/src/libutil/args.cc +++ b/src/libutil/args.cc @@ -102,9 +102,11 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end) ++pos; Strings args; for (size_t n = 0 ; n < flag.arity; ++n) { - if (pos == end) + if (pos == end) { + if (flag.arity == ArityAny) break; throw UsageError(format("flag '%1%' requires %2% argument(s)") % name % flag.arity); + } args.push_back(*pos++); } flag.handler(args); diff --git a/src/libutil/args.hh b/src/libutil/args.hh index fd910b965..044ed209e 100644 --- a/src/libutil/args.hh +++ b/src/libutil/args.hh @@ -26,6 +26,8 @@ public: protected: + static const size_t ArityAny = std::numeric_limits::max(); + /* Flags. */ struct Flag { diff --git a/src/nix/run.cc b/src/nix/run.cc index e58e2f187..39fbcc8ac 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -17,8 +17,20 @@ std::string chrootHelperName = "__run_in_chroot"; struct CmdRun : InstallablesCommand { + Strings command = { "bash" }; + CmdRun() { + mkFlag() + .longName("command") + .shortName('c') + .description("command and arguments to be executed; defaults to 'bash'") + .arity(ArityAny) + .labels({"command", "args"}) + .handler([&](Strings ss) { + if (ss.empty()) throw UsageError("--command requires at least one argument"); + command = ss; + }); } std::string name() override @@ -43,8 +55,8 @@ struct CmdRun : InstallablesCommand unixPath.push_front(path + "/bin"); setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1); - std::string cmd = "bash"; - Strings args = { cmd }; + std::string cmd = *command.begin(); + Strings args = command; /* If this is a diverted store (i.e. its "logical" location (typically /nix/store) differs from its "physical" location