Files
lix/src/libexpr/primops/system.cc
T
Tom Hubrecht 4ea0f70b8b primops: Explicit registering of primops
Change-Id: I05e72d2bfdc715d9e27cc672ac35619310b0864d
2024-05-30 12:57:17 +02:00

102 lines
3.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "eval-settings.hh"
#include "primops.hh"
namespace nix {
/**
* builtins.exec
*/
void prim_exec(EvalState & state, const PosIdx pos, Value ** args, Value & v)
{
state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.exec");
auto elems = args[0]->listElems();
auto count = args[0]->listSize();
if (count == 0) {
state.error<EvalError>("at least one argument to 'exec' required").atPos(pos).debugThrow();
}
NixStringContext context;
auto program =
state
.coerceToString(
pos,
*elems[0],
context,
"while evaluating the first element of the argument passed to builtins.exec",
false,
false
)
.toOwned();
Strings commandArgs;
for (unsigned int i = 1; i < args[0]->listSize(); ++i) {
commandArgs.push_back(
state
.coerceToString(
pos,
*elems[i],
context,
"while evaluating an element of the argument passed to builtins.exec",
false,
false
)
.toOwned()
);
}
try {
auto _ = state.realiseContext(context); // FIXME: Handle CA derivations
} catch (InvalidPathError & e) {
state
.error<EvalError>(
"cannot execute '%1%', since path '%2%' is not valid", program, e.path
)
.atPos(pos)
.debugThrow();
}
auto output = runProgram(program, true, commandArgs);
Expr * parsed;
try {
parsed = state.parseExprFromString(std::move(output), state.rootPath(CanonPath::root));
} catch (Error & e) {
e.addTrace(state.positions[pos], "while parsing the output from '%1%'", program);
throw;
}
try {
state.eval(parsed, v);
} catch (Error & e) {
e.addTrace(state.positions[pos], "while evaluating the output from '%1%'", program);
throw;
}
}
/**
* builtins.getEnv
*/
static void prim_getEnv(EvalState & state, const PosIdx pos, Value ** args, Value & v)
{
std::string name(state.forceStringNoCtx(
*args[0], pos, "while evaluating the first argument passed to builtins.getEnv"
));
v.mkString(evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name).value_or(""));
}
PrimOp primop_getEnv({
.name = "__getEnv",
.args = {"s"},
.doc = R"(
`getEnv` returns the value of the environment variable *s*, or an
empty string if the variable doesnt exist. This function should be
used with care, as it can introduce all sorts of nasty environment
dependencies in your Nix expression.
`getEnv` is used in Nix Packages to locate the file
`~/.nixpkgs/config.nix`, which contains user-local settings for Nix
Packages. (That is, it does a `getEnv "HOME"` to locate the users
home directory.)
)",
.fun = prim_getEnv,
});
}