diff --git a/src/exec.cc b/src/exec.cc index 5d71408274..d82f5effaa 100644 --- a/src/exec.cc +++ b/src/exec.cc @@ -35,7 +35,8 @@ public: /* Run a program. */ -void runProgram(const string & program, Environment env) +void runProgram(const string & program, + const Strings & args, const Environment & env) { /* Create a log file. */ string logFileName = nixLogDir + "/run.log"; @@ -68,15 +69,25 @@ void runProgram(const string & program, Environment env) if (chdir(tmpDir.c_str()) == -1) throw SysError(format("changing into to `%1%'") % tmpDir); - /* Fill in the environment. We don't bother freeing - the strings, since we'll exec or die soon - anyway. */ - const char * env2[env.size() + 1]; - int i = 0; - for (Environment::iterator it = env.begin(); - it != env.end(); it++, i++) - env2[i] = (new string(it->first + "=" + it->second))->c_str(); - env2[i] = 0; + /* Fill in the arguments. */ + const char * argArr[args.size() + 2]; + const char * * p = argArr; + string progName = baseNameOf(program); + *p++ = progName.c_str(); + for (Strings::const_iterator i = args.begin(); + i != args.end(); i++) + *p++ = i->c_str(); + *p = 0; + + /* Fill in the environment. */ + Strings envStrs; + const char * envArr[env.size() + 1]; + p = envArr; + for (Environment::const_iterator i = env.begin(); + i != env.end(); i++) + *p++ = envStrs.insert(envStrs.end(), + i->first + "=" + i->second)->c_str(); + *p = 0; /* Dup the log handle into stderr. */ if (dup2(fileno(logFile), STDERR_FILENO) == -1) @@ -87,7 +98,7 @@ void runProgram(const string & program, Environment env) throw SysError("cannot dup stderr into stdout"); /* Execute the program. This should not return. */ - execle(program.c_str(), baseNameOf(program).c_str(), 0, env2); + execve(program.c_str(), (char * *) argArr, (char * *) envArr); throw SysError(format("unable to execute %1%") % program); diff --git a/src/exec.hh b/src/exec.hh index 9dc8e0cd02..8d410e4043 100644 --- a/src/exec.hh +++ b/src/exec.hh @@ -4,6 +4,8 @@ #include #include +#include "util.hh" + using namespace std; @@ -12,7 +14,8 @@ typedef map Environment; /* Run a program. */ -void runProgram(const string & program, Environment env); +void runProgram(const string & program, + const Strings & args, const Environment & env); #endif /* !__EXEC_H */ diff --git a/src/fstate.cc b/src/fstate.cc index 2e2857ffc9..47a93901fe 100644 --- a/src/fstate.cc +++ b/src/fstate.cc @@ -120,13 +120,19 @@ static bool parseSlice(ATerm t, Slice & slice) static bool parseDerive(ATerm t, Derive & derive) { - ATermList outs, ins, bnds; + ATermList outs, ins, args, bnds; char * builder; char * platform; - if (!ATmatch(t, "Derive([], [], , , [])", - &outs, &ins, &builder, &platform, &bnds)) - return false; + if (!ATmatch(t, "Derive([], [], , , [], [])", + &outs, &ins, &platform, &builder, &args, &bnds)) + { + /* !!! compatibility -> remove eventually */ + if (!ATmatch(t, "Derive([], [], , , [])", + &outs, &ins, &builder, &platform, &bnds)) + return false; + args = ATempty; + } while (!ATisEmpty(outs)) { char * s1, * s2; @@ -142,6 +148,15 @@ static bool parseDerive(ATerm t, Derive & derive) derive.builder = builder; derive.platform = platform; + while (!ATisEmpty(args)) { + char * s; + ATerm arg = ATgetFirst(args); + if (!ATmatch(arg, "", &s)) + throw badTerm("string expected", arg); + derive.args.push_back(s); + args = ATgetNext(args); + } + while (!ATisEmpty(bnds)) { char * s1, * s2; ATerm bnd = ATgetFirst(bnds); @@ -204,6 +219,11 @@ static ATerm unparseDerive(const Derive & derive) ATmake("(, )", i->first.c_str(), ((string) i->second).c_str())); + ATermList args = ATempty; + for (Strings::const_iterator i = derive.args.begin(); + i != derive.args.end(); i++) + args = ATinsert(args, ATmake("", i->c_str())); + ATermList env = ATempty; for (StringPairs::const_iterator i = derive.env.begin(); i != derive.env.end(); i++) @@ -211,11 +231,12 @@ static ATerm unparseDerive(const Derive & derive) ATmake("(, )", i->first.c_str(), i->second.c_str())); - return ATmake("Derive(, , , , )", + return ATmake("Derive(, , , , , )", ATreverse(outs), unparseIds(derive.inputs), - derive.builder.c_str(), derive.platform.c_str(), + derive.builder.c_str(), + ATreverse(args), ATreverse(env)); } diff --git a/src/fstate.hh b/src/fstate.hh index 969abe9e06..b71739aed9 100644 --- a/src/fstate.hh +++ b/src/fstate.hh @@ -36,8 +36,9 @@ struct Derive { DeriveOutputs outputs; FSIds inputs; - string builder; string platform; + string builder; + Strings args; StringPairs env; }; diff --git a/src/normalise.cc b/src/normalise.cc index 2fa6f7f401..3d025d5f5a 100644 --- a/src/normalise.cc +++ b/src/normalise.cc @@ -169,7 +169,7 @@ FSId normaliseFState(FSId id, FSIdSet pending) /* Run the builder. */ msg(lvlChatty, format("building...")); - runProgram(fs.derive.builder, env); + runProgram(fs.derive.builder, fs.derive.args, env); msg(lvlChatty, format("build completed")); } else