diff options
Diffstat (limited to 'tools/perf/util/pager.c')
| -rw-r--r-- | tools/perf/util/pager.c | 99 | 
1 files changed, 99 insertions, 0 deletions
diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c new file mode 100644 index 00000000000..a28bccae545 --- /dev/null +++ b/tools/perf/util/pager.c @@ -0,0 +1,99 @@ +#include "cache.h" +#include "run-command.h" +#include "sigchain.h" + +/* + * This is split up from the rest of git so that we can do + * something different on Windows. + */ + +static int spawned_pager; + +#ifndef __MINGW32__ +static void pager_preexec(void) +{ +	/* +	 * Work around bug in "less" by not starting it until we +	 * have real input +	 */ +	fd_set in; + +	FD_ZERO(&in); +	FD_SET(0, &in); +	select(1, &in, NULL, &in, NULL); + +	setenv("LESS", "FRSX", 0); +} +#endif + +static const char *pager_argv[] = { "sh", "-c", NULL, NULL }; +static struct child_process pager_process; + +static void wait_for_pager(void) +{ +	fflush(stdout); +	fflush(stderr); +	/* signal EOF to pager */ +	close(1); +	close(2); +	finish_command(&pager_process); +} + +static void wait_for_pager_signal(int signo) +{ +	wait_for_pager(); +	sigchain_pop(signo); +	raise(signo); +} + +void setup_pager(void) +{ +	const char *pager = getenv("PERF_PAGER"); + +	if (!isatty(1)) +		return; +	if (!pager) { +		if (!pager_program) +			perf_config(perf_default_config, NULL); +		pager = pager_program; +	} +	if (!pager) +		pager = getenv("PAGER"); +	if (!pager) +		pager = "less"; +	else if (!*pager || !strcmp(pager, "cat")) +		return; + +	spawned_pager = 1; /* means we are emitting to terminal */ + +	/* spawn the pager */ +	pager_argv[2] = pager; +	pager_process.argv = pager_argv; +	pager_process.in = -1; +#ifndef __MINGW32__ +	pager_process.preexec_cb = pager_preexec; +#endif +	if (start_command(&pager_process)) +		return; + +	/* original process continues, but writes to the pipe */ +	dup2(pager_process.in, 1); +	if (isatty(2)) +		dup2(pager_process.in, 2); +	close(pager_process.in); + +	/* this makes sure that the parent terminates after the pager */ +	sigchain_push_common(wait_for_pager_signal); +	atexit(wait_for_pager); +} + +int pager_in_use(void) +{ +	const char *env; + +	if (spawned_pager) +		return 1; + +	env = getenv("PERF_PAGER_IN_USE"); +	return env ? perf_config_bool("PERF_PAGER_IN_USE", env) : 0; +}  | 
