pager.c 1.9 KB

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