1#include "cache.h" 2#include "run-command.h" 3#include "sigchain.h" 4 5/* 6 * This is split up from the rest of git so that we can do 7 * something different on Windows. 8 */ 9 10static int spawned_pager; 11 12static void pager_preexec(void) 13{ 14 fd_set in; 15 16 FD_ZERO(&in); 17 FD_SET(0, &in); 18 select(1, &in, NULL, &in, NULL); 19 20 setenv("LESS", "FRSX", 0); 21} 22 23static const char *pager_argv[] = { "sh", "-c", NULL, NULL }; 24static struct child_process pager_process; 25 26static void wait_for_pager(void) 27{ 28 fflush(stdout); 29 fflush(stderr); 30 /* signal EOF to pager */ 31 close(1); 32 close(2); 33 finish_command(&pager_process); 34} 35 36static void wait_for_pager_signal(int signo) 37{ 38 wait_for_pager(); 39 sigchain_pop(signo); 40 raise(signo); 41} 42 43void setup_pager(void) 44{ 45 const char *pager = getenv("PERF_PAGER"); 46 47 if (!isatty(1)) 48 return; 49 if (!pager) { 50 if (!pager_program) 51 perf_config(perf_default_config, NULL); 52 pager = pager_program; 53 } 54 if (!pager) 55 pager = getenv("PAGER"); 56 if (!pager) 57 pager = "less"; 58 else if (!*pager || !strcmp(pager, "cat")) 59 return; 60 61 spawned_pager = 1; /* means we are emitting to terminal */ 62 63 /* spawn the pager */ 64 pager_argv[2] = pager; 65 pager_process.argv = pager_argv; 66 pager_process.in = -1; 67 pager_process.preexec_cb = pager_preexec; 68 69 if (start_command(&pager_process)) 70 return; 71 72 /* original process continues, but writes to the pipe */ 73 dup2(pager_process.in, 1); 74 if (isatty(2)) 75 dup2(pager_process.in, 2); 76 close(pager_process.in); 77 78 /* this makes sure that the parent terminates after the pager */ 79 sigchain_push_common(wait_for_pager_signal); 80 atexit(wait_for_pager); 81} 82 83int pager_in_use(void) 84{ 85 const char *env; 86 87 if (spawned_pager) 88 return 1; 89 90 env = getenv("PERF_PAGER_IN_USE"); 91 return env ? perf_config_bool("PERF_PAGER_IN_USE", env) : 0; 92} 93