Merge branch 'bs/maint-1.6.0-tree-walk-prefix' into maint-1.6.1
[git] / pager.c
1 #include "cache.h"
2 #include "run-command.h"
3
4 /*
5  * This is split up from the rest of git so that we can do
6  * something different on Windows.
7  */
8
9 static int spawned_pager;
10
11 #ifndef __MINGW32__
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 #endif
27
28 static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
29 static struct child_process pager_process;
30
31 static void wait_for_pager(void)
32 {
33         fflush(stdout);
34         fflush(stderr);
35         /* signal EOF to pager */
36         close(1);
37         close(2);
38         finish_command(&pager_process);
39 }
40
41 void setup_pager(void)
42 {
43         const char *pager = getenv("GIT_PAGER");
44
45         if (!isatty(1))
46                 return;
47         if (!pager) {
48                 if (!pager_program)
49                         git_config(git_default_config, NULL);
50                 pager = pager_program;
51         }
52         if (!pager)
53                 pager = getenv("PAGER");
54         if (!pager)
55                 pager = "less";
56         else if (!*pager || !strcmp(pager, "cat"))
57                 return;
58
59         spawned_pager = 1; /* means we are emitting to terminal */
60
61         /* spawn the pager */
62         pager_argv[2] = pager;
63         pager_process.argv = pager_argv;
64         pager_process.in = -1;
65 #ifndef __MINGW32__
66         pager_process.preexec_cb = pager_preexec;
67 #endif
68         if (start_command(&pager_process))
69                 return;
70
71         /* original process continues, but writes to the pipe */
72         dup2(pager_process.in, 1);
73         if (isatty(2))
74                 dup2(pager_process.in, 2);
75         close(pager_process.in);
76
77         /* this makes sure that the parent terminates after the pager */
78         atexit(wait_for_pager);
79 }
80
81 int pager_in_use(void)
82 {
83         const char *env;
84
85         if (spawned_pager)
86                 return 1;
87
88         env = getenv("GIT_PAGER_IN_USE");
89         return env ? git_config_bool("GIT_PAGER_IN_USE", env) : 0;
90 }