aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-06-27 11:18:54 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-06-27 11:18:54 +0200
commitd7be6d45d97e89653b77686bdb39b833afbcf6ca (patch)
tree74d8e8f480979061d1b1b09198fa671f774f7af9
parent9d0709e8c47082cec35d6412053eacfadae23bcd (diff)
parentd62f46e500958bc97ae6837911e27c20a47cc181 (diff)
Merge branch 'shlevy-import-native'
-rw-r--r--src/libexpr/local.mk2
-rw-r--r--src/libexpr/primops.cc43
-rw-r--r--src/libstore/globals.cc2
-rw-r--r--src/libstore/globals.hh3
4 files changed, 50 insertions, 0 deletions
diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk
index b3b408691..75a0e185e 100644
--- a/src/libexpr/local.mk
+++ b/src/libexpr/local.mk
@@ -8,6 +8,8 @@ libexpr_SOURCES := $(wildcard $(d)/*.cc) $(d)/lexer-tab.cc $(d)/parser-tab.cc
libexpr_LIBS = libutil libstore libformat
+libexpr_LDFLAGS = -ldl
+
# The dependency on libgc must be propagated (i.e. meaning that
# programs/libraries that use libexpr must explicitly pass -lgc),
# because inline functions in libexpr's header files call libgc.
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 366911b54..ff82f36b5 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -15,6 +15,7 @@
#include <algorithm>
#include <cstring>
+#include <dlfcn.h>
namespace nix {
@@ -129,6 +130,46 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
}
+/* Want reasonable symbol names, so extern C */
+/* !!! Should we pass the Pos or the file name too? */
+extern "C" typedef void (*ValueInitializer)(EvalState & state, Value & v);
+
+/* Load a ValueInitializer from a dso and return whatever it initializes */
+static void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+ PathSet context;
+ Path path = state.coerceToPath(pos, *args[0], context);
+
+ try {
+ realiseContext(context);
+ } catch (InvalidPathError & e) {
+ throw EvalError(format("cannot import `%1%', since path `%2%' is not valid, at %3%")
+ % path % e.path % pos);
+ }
+
+ string sym = state.forceStringNoCtx(*args[1], pos);
+
+ void *handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
+ if (!handle)
+ throw EvalError(format("could not open `%1%': %2%") % path % dlerror());
+
+ dlerror();
+ ValueInitializer func = (ValueInitializer) dlsym(handle, sym.c_str());
+ if(!func) {
+ char *message = dlerror();
+ if (message)
+ throw EvalError(format("could not load symbol `%1%' from `%2%': %3%") % sym % path % message);
+ else
+ throw EvalError(format("symbol `%1%' from `%2%' resolved to NULL when a function pointer was expected")
+ % sym % path);
+ }
+
+ (func)(state, v);
+
+ /* We don't dlclose because v may be a primop referencing a function in the shared object file */
+}
+
+
/* Return a string representing the type of the expression. */
static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
@@ -1327,6 +1368,8 @@ void EvalState::createBaseEnv()
mkApp(v, *baseEnv.values[baseEnvDispl - 1], *v2);
forceValue(v);
addConstant("import", v);
+ if (settings.enableImportNative)
+ addPrimOp("__importNative", 2, prim_importNative);
addPrimOp("__typeOf", 1, prim_typeOf);
addPrimOp("isNull", 1, prim_isNull);
addPrimOp("__isFunction", 1, prim_isFunction);
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index 180344e33..5d359e128 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -61,6 +61,7 @@ Settings::Settings()
envKeepDerivations = false;
lockCPU = getEnv("NIX_AFFINITY_HACK", "1") == "1";
showTrace = false;
+ enableImportNative = false;
}
@@ -148,6 +149,7 @@ void Settings::update()
get(sshSubstituterHosts, "ssh-substituter-hosts");
get(useSshSubstituter, "use-ssh-substituter");
get(logServers, "log-servers");
+ get(enableImportNative, "allow-arbitrary-code-during-evaluation");
string subs = getEnv("NIX_SUBSTITUTERS", "default");
if (subs == "default") {
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 65a6c388b..8dd59a9c7 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -200,6 +200,9 @@ struct Settings {
/* A list of URL prefixes that can return Nix build logs. */
Strings logServers;
+ /* Whether the importNative primop should be enabled */
+ bool enableImportNative;
+
private:
SettingsMap settings, overrides;