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