nix-store -l: Automatically pipe output into $PAGER
This commit is contained in:
		
							parent
							
								
									894fa5e42d
								
							
						
					
					
						commit
						392430b2c4
					
				
					 4 changed files with 56 additions and 2 deletions
				
			
		|  | @ -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); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -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"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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)); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue