about summary refs log tree commit diff
path: root/src/libmain/shared.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-08-20T13·12+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-08-20T13·12+0200
commit392430b2c4ceb2e476abe2b3acc928581b2a1445 (patch)
tree30db8572f28c8def55f3b4dcce988a6ed4c778e9 /src/libmain/shared.cc
parent894fa5e42dd952caa702794964a13845ccf6f29a (diff)
nix-store -l: Automatically pipe output into $PAGER
Diffstat (limited to 'src/libmain/shared.cc')
-rw-r--r--src/libmain/shared.cc40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index 9ac9d27738..ba75847fdb 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -285,4 +285,44 @@ int handleExceptions(const string & programName, std::function<void()> fun)
 }
 
 
+RunPager::RunPager()
+{
+    string pager = getEnv("PAGER");
+    if (!isatty(STDOUT_FILENO) || pager.empty()) return;
+
+    /* Ignore SIGINT. The pager will handle it (and we'll get
+       SIGPIPE). */
+    struct sigaction act;
+    act.sa_handler = SIG_IGN;
+    act.sa_flags = 0;
+    sigemptyset(&act.sa_mask);
+    if (sigaction(SIGINT, &act, 0)) throw SysError("ignoring SIGINT");
+
+    restoreSIGPIPE();
+
+    Pipe toPager;
+    toPager.create();
+
+    pid = startProcess([&]() {
+        if (dup2(toPager.readSide, STDIN_FILENO) == -1)
+            throw SysError("dupping stdin");
+        execl("/bin/sh", "sh", "-c", pager.c_str(), NULL);
+        throw SysError(format("executing `%1%'") % pager);
+    });
+
+    if (dup2(toPager.writeSide, STDOUT_FILENO) == -1)
+        throw SysError("dupping stdout");
+
+}
+
+
+RunPager::~RunPager()
+{
+    if (pid != -1) {
+        close(STDOUT_FILENO);
+        pid.wait(true);
+    }
+}
+
+
 }