Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v4.7 100 lines 2.0 kB view raw
1#include <sys/select.h> 2#include <stdlib.h> 3#include <stdio.h> 4#include <string.h> 5#include <signal.h> 6#include "pager.h" 7#include "run-command.h" 8#include "sigchain.h" 9#include "subcmd-config.h" 10 11/* 12 * This is split up from the rest of git so that we can do 13 * something different on Windows. 14 */ 15 16static int spawned_pager; 17 18void pager_init(const char *pager_env) 19{ 20 subcmd_config.pager_env = pager_env; 21} 22 23static void pager_preexec(void) 24{ 25 /* 26 * Work around bug in "less" by not starting it until we 27 * have real input 28 */ 29 fd_set in; 30 31 FD_ZERO(&in); 32 FD_SET(0, &in); 33 select(1, &in, NULL, &in, NULL); 34 35 setenv("LESS", "FRSX", 0); 36} 37 38static const char *pager_argv[] = { "sh", "-c", NULL, NULL }; 39static struct child_process pager_process; 40 41static void wait_for_pager(void) 42{ 43 fflush(stdout); 44 fflush(stderr); 45 /* signal EOF to pager */ 46 close(1); 47 close(2); 48 finish_command(&pager_process); 49} 50 51static void wait_for_pager_signal(int signo) 52{ 53 wait_for_pager(); 54 sigchain_pop(signo); 55 raise(signo); 56} 57 58void setup_pager(void) 59{ 60 const char *pager = getenv(subcmd_config.pager_env); 61 62 if (!isatty(1)) 63 return; 64 if (!pager) 65 pager = getenv("PAGER"); 66 if (!(pager || access("/usr/bin/pager", X_OK))) 67 pager = "/usr/bin/pager"; 68 if (!(pager || access("/usr/bin/less", X_OK))) 69 pager = "/usr/bin/less"; 70 if (!pager) 71 pager = "cat"; 72 if (!*pager || !strcmp(pager, "cat")) 73 return; 74 75 spawned_pager = 1; /* means we are emitting to terminal */ 76 77 /* spawn the pager */ 78 pager_argv[2] = pager; 79 pager_process.argv = pager_argv; 80 pager_process.in = -1; 81 pager_process.preexec_cb = pager_preexec; 82 83 if (start_command(&pager_process)) 84 return; 85 86 /* original process continues, but writes to the pipe */ 87 dup2(pager_process.in, 1); 88 if (isatty(2)) 89 dup2(pager_process.in, 2); 90 close(pager_process.in); 91 92 /* this makes sure that the parent terminates after the pager */ 93 sigchain_push_common(wait_for_pager_signal); 94 atexit(wait_for_pager); 95} 96 97int pager_in_use(void) 98{ 99 return spawned_pager; 100}