nix-store -l: Automatically pipe output into $PAGER

This commit is contained in:
Eelco Dolstra 2014-08-20 15:12:58 +02:00
parent 894fa5e42d
commit 392430b2c4
4 changed files with 56 additions and 2 deletions

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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");
}

View file

@ -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));