guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

143/376: nix-store -l: Automatically pipe output into $PAGER


From: Ludovic Courtès
Subject: 143/376: nix-store -l: Automatically pipe output into $PAGER
Date: Wed, 28 Jan 2015 22:04:37 +0000

civodul pushed a commit to tag 1.8
in repository guix.

commit 392430b2c4ceb2e476abe2b3acc928581b2a1445
Author: Eelco Dolstra <address@hidden>
Date:   Wed Aug 20 15:12:58 2014 +0200

    nix-store -l: Automatically pipe output into $PAGER
---
 src/libmain/shared.cc      |   40 ++++++++++++++++++++++++++++++++++++++++
 src/libmain/shared.hh      |   12 ++++++++++++
 src/libutil/util.cc        |    4 ++--
 src/nix-store/nix-store.cc |    2 ++
 4 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index 9ac9d27..ba75847 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);
+    }
+}
+
+
 }
diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh
index c74e7cb..c56203d 100644
--- a/src/libmain/shared.hh
+++ b/src/libmain/shared.hh
@@ -69,6 +69,18 @@ template<class N> N getIntArg(const string & opt,
 /* Show the manual page for the specified program. */
 void showManPage(const string & name);
 
+/* The constructor of this class starts a pager if stdout is a
+   terminal and $PAGER is set. Stdout is redirected to the pager. */
+class RunPager
+{
+public:
+    RunPager();
+    ~RunPager();
+
+private:
+    Pid pid;
+};
+
 extern volatile ::sig_atomic_t blockInt;
 
 }
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index ed283fb..14aab7c 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -931,11 +931,11 @@ void closeOnExec(int fd)
 
 void restoreSIGPIPE()
 {
-    struct sigaction act, oact;
+    struct sigaction act;
     act.sa_handler = SIG_DFL;
     act.sa_flags = 0;
     sigemptyset(&act.sa_mask);
-    if (sigaction(SIGPIPE, &act, &oact)) throw SysError("resetting SIGPIPE");
+    if (sigaction(SIGPIPE, &act, 0)) throw SysError("resetting SIGPIPE");
 }
 
 
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 6a297b4..abe4c7e 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -459,6 +459,8 @@ static void opReadLog(Strings opFlags, Strings opArgs)
 {
     if (!opFlags.empty()) throw UsageError("unknown flag");
 
+    RunPager pager;
+
     foreach (Strings::iterator, i, opArgs) {
         Path path = useDeriver(followLinksToStorePath(*i));
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]