Home | History | Annotate | Download | only in util
      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 
     10 static int spawned_pager;
     11 
     12 static void pager_preexec(void)
     13 {
     14 	/*
     15 	 * Work around bug in "less" by not starting it until we
     16 	 * have real input
     17 	 */
     18 	fd_set in;
     19 
     20 	FD_ZERO(&in);
     21 	FD_SET(0, &in);
     22 	select(1, &in, NULL, &in, NULL);
     23 
     24 	setenv("LESS", "FRSX", 0);
     25 }
     26 
     27 static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
     28 static struct child_process pager_process;
     29 
     30 static void wait_for_pager(void)
     31 {
     32 	fflush(stdout);
     33 	fflush(stderr);
     34 	/* signal EOF to pager */
     35 	close(1);
     36 	close(2);
     37 	finish_command(&pager_process);
     38 }
     39 
     40 static void wait_for_pager_signal(int signo)
     41 {
     42 	wait_for_pager();
     43 	sigchain_pop(signo);
     44 	raise(signo);
     45 }
     46 
     47 void setup_pager(void)
     48 {
     49         /* ANDROID_CHANGE_BEGIN */
     50 #ifdef __BIONIC__
     51         return;
     52 #else
     53 	const char *pager = getenv("PERF_PAGER");
     54 
     55 	if (!isatty(1))
     56 		return;
     57 	if (!pager) {
     58 		if (!pager_program)
     59 			perf_config(perf_default_config, NULL);
     60 		pager = pager_program;
     61 	}
     62 	if (!pager)
     63 		pager = getenv("PAGER");
     64 	if (!pager)
     65 		pager = "less";
     66 	else if (!*pager || !strcmp(pager, "cat"))
     67 		return;
     68 
     69 	spawned_pager = 1; /* means we are emitting to terminal */
     70 
     71 	/* spawn the pager */
     72 	pager_argv[2] = pager;
     73 	pager_process.argv = pager_argv;
     74 	pager_process.in = -1;
     75 	pager_process.preexec_cb = pager_preexec;
     76 
     77 	if (start_command(&pager_process))
     78 		return;
     79 
     80 	/* original process continues, but writes to the pipe */
     81 	dup2(pager_process.in, 1);
     82 	if (isatty(2))
     83 		dup2(pager_process.in, 2);
     84 	close(pager_process.in);
     85 
     86 	/* this makes sure that the parent terminates after the pager */
     87 	sigchain_push_common(wait_for_pager_signal);
     88 	atexit(wait_for_pager);
     89 #endif
     90         /* ANDROID_CHANGE_END */
     91 }
     92 
     93 int pager_in_use(void)
     94 {
     95 	const char *env;
     96 
     97 	if (spawned_pager)
     98 		return 1;
     99 
    100 	env = getenv("PERF_PAGER_IN_USE");
    101 	return env ? perf_config_bool("PERF_PAGER_IN_USE", env) : 0;
    102 }
    103