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