aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2021-01-14 00:05:04 +0100
committerEelco Dolstra <edolstra@gmail.com>2021-01-14 00:05:04 +0100
commit7a472a76d4dcbbd0eb7832c0bdcb120d32881e8b (patch)
treeae0c8e77b6b89239dea45b62918f0ba42c651f5c
parent28ef6ebf914792f9e543e9778248f06e716a859d (diff)
Add 'nix daemon' command
-rw-r--r--src/nix/command.hh2
-rw-r--r--src/nix/daemon.cc (renamed from src/nix-daemon/nix-daemon.cc)114
-rw-r--r--src/nix/daemon.md21
-rw-r--r--src/nix/main.cc3
-rw-r--r--tests/common.sh.in2
5 files changed, 98 insertions, 44 deletions
diff --git a/src/nix/command.hh b/src/nix/command.hh
index 3aae57edd..f325cd906 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -13,6 +13,8 @@ namespace nix {
extern std::string programPath;
+extern char * * savedArgv;
+
class EvalState;
struct Pos;
class Store;
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix/daemon.cc
index 9227369b8..204d4ce6b 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix/daemon.cc
@@ -1,3 +1,4 @@
+#include "command.hh"
#include "shared.hh"
#include "local-store.hh"
#include "remote-store.hh"
@@ -150,7 +151,7 @@ static ref<Store> openUncachedStore()
}
-static void daemonLoop(char * * argv)
+static void daemonLoop()
{
if (chdir("/") == -1)
throw SysError("cannot change current directory");
@@ -232,9 +233,9 @@ static void daemonLoop(char * * argv)
setSigChldAction(false);
// For debugging, stuff the pid into argv[1].
- if (peer.pidKnown && argv[1]) {
+ if (peer.pidKnown && savedArgv[1]) {
string processName = std::to_string(peer.pid);
- strncpy(argv[1], processName.c_str(), strlen(argv[1]));
+ strncpy(savedArgv[1], processName.c_str(), strlen(savedArgv[1]));
}
// Handle the connection.
@@ -264,6 +265,48 @@ static void daemonLoop(char * * argv)
}
}
+static void runDaemon(bool stdio)
+{
+ if (stdio) {
+ if (auto store = openUncachedStore().dynamic_pointer_cast<RemoteStore>()) {
+ auto conn = store->openConnectionWrapper();
+ int from = conn->from.fd;
+ int to = conn->to.fd;
+
+ auto nfds = std::max(from, STDIN_FILENO) + 1;
+ while (true) {
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(from, &fds);
+ FD_SET(STDIN_FILENO, &fds);
+ if (select(nfds, &fds, nullptr, nullptr, nullptr) == -1)
+ throw SysError("waiting for data from client or server");
+ if (FD_ISSET(from, &fds)) {
+ auto res = splice(from, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
+ if (res == -1)
+ throw SysError("splicing data from daemon socket to stdout");
+ else if (res == 0)
+ throw EndOfFile("unexpected EOF from daemon socket");
+ }
+ if (FD_ISSET(STDIN_FILENO, &fds)) {
+ auto res = splice(STDIN_FILENO, nullptr, to, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
+ if (res == -1)
+ throw SysError("splicing data from stdin to daemon socket");
+ else if (res == 0)
+ return;
+ }
+ }
+ } else {
+ FdSource from(STDIN_FILENO);
+ FdSink to(STDOUT_FILENO);
+ /* Auth hook is empty because in this mode we blindly trust the
+ standard streams. Limiting access to those is explicitly
+ not `nix-daemon`'s responsibility. */
+ processConnection(openUncachedStore(), from, to, Trusted, NotRecursive, [&](Store & _){});
+ }
+ } else
+ daemonLoop();
+}
static int main_nix_daemon(int argc, char * * argv)
{
@@ -285,49 +328,34 @@ static int main_nix_daemon(int argc, char * * argv)
initPlugins();
- if (stdio) {
- if (auto store = openUncachedStore().dynamic_pointer_cast<RemoteStore>()) {
- auto conn = store->openConnectionWrapper();
- int from = conn->from.fd;
- int to = conn->to.fd;
-
- auto nfds = std::max(from, STDIN_FILENO) + 1;
- while (true) {
- fd_set fds;
- FD_ZERO(&fds);
- FD_SET(from, &fds);
- FD_SET(STDIN_FILENO, &fds);
- if (select(nfds, &fds, nullptr, nullptr, nullptr) == -1)
- throw SysError("waiting for data from client or server");
- if (FD_ISSET(from, &fds)) {
- auto res = splice(from, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
- if (res == -1)
- throw SysError("splicing data from daemon socket to stdout");
- else if (res == 0)
- throw EndOfFile("unexpected EOF from daemon socket");
- }
- if (FD_ISSET(STDIN_FILENO, &fds)) {
- auto res = splice(STDIN_FILENO, nullptr, to, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
- if (res == -1)
- throw SysError("splicing data from stdin to daemon socket");
- else if (res == 0)
- return 0;
- }
- }
- } else {
- FdSource from(STDIN_FILENO);
- FdSink to(STDOUT_FILENO);
- /* Auth hook is empty because in this mode we blindly trust the
- standard streams. Limiting access to those is explicitly
- not `nix-daemon`'s responsibility. */
- processConnection(openUncachedStore(), from, to, Trusted, NotRecursive, [&](Store & _){});
- }
- } else {
- daemonLoop(argv);
- }
+ runDaemon(stdio);
return 0;
}
}
static RegisterLegacyCommand r_nix_daemon("nix-daemon", main_nix_daemon);
+
+struct CmdDaemon : StoreCommand
+{
+ std::string description() override
+ {
+ return "daemon to perform store operations on behalf of non-root clients";
+ }
+
+ Category category() override { return catUtility; }
+
+ std::string doc() override
+ {
+ return
+ #include "daemon.md"
+ ;
+ }
+
+ void run(ref<Store> store) override
+ {
+ runDaemon(false);
+ }
+};
+
+static auto rCmdDaemon = registerCommand2<CmdDaemon>({"daemon"});
diff --git a/src/nix/daemon.md b/src/nix/daemon.md
new file mode 100644
index 000000000..e97016a94
--- /dev/null
+++ b/src/nix/daemon.md
@@ -0,0 +1,21 @@
+R""(
+
+# Example
+
+* Run the daemon in the foreground:
+
+ ```console
+ # nix daemon
+ ```
+
+# Description
+
+This command runs the Nix daemon, which is a required component in
+multi-user Nix installations. It performs build actions and other
+operations on the Nix store on behalf of non-root users. Usually you
+don't run the daemon directly; instead it's managed by a service
+management framework such as `systemd`.
+
+Note that this daemon does not fork into the background.
+
+)""
diff --git a/src/nix/main.cc b/src/nix/main.cc
index 398526020..418396280 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -52,6 +52,7 @@ static bool haveInternet()
}
std::string programPath;
+char * * savedArgv;
struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
{
@@ -232,6 +233,8 @@ static auto rCmdHelp = registerCommand<CmdHelp>("help");
void mainWrapped(int argc, char * * argv)
{
+ savedArgv = argv;
+
/* The chroot helper needs to be run before any threads have been
started. */
if (argc > 0 && argv[0] == chrootHelperName) {
diff --git a/tests/common.sh.in b/tests/common.sh.in
index 5489c0c44..e3bcab507 100644
--- a/tests/common.sh.in
+++ b/tests/common.sh.in
@@ -73,7 +73,7 @@ startDaemon() {
# Start the daemon, wait for the socket to appear. !!!
# ‘nix-daemon’ should have an option to fork into the background.
rm -f $NIX_STATE_DIR/daemon-socket/socket
- nix-daemon &
+ nix daemon &
for ((i = 0; i < 30; i++)); do
if [ -e $NIX_DAEMON_SOCKET_PATH ]; then break; fi
sleep 1