Merge git://git.kernel.org/pub/scm/gitk/gitk
[git] / pager.c
1 #include "cache.h"
2
3 /*
4  * This is split up from the rest of git so that we might do
5  * something different on Windows, for example.
6  */
7
8 static int spawned_pager;
9
10 static void run_pager(const char *pager)
11 {
12         /*
13          * Work around bug in "less" by not starting it until we
14          * have real input
15          */
16         fd_set in;
17
18         FD_ZERO(&in);
19         FD_SET(0, &in);
20         select(1, &in, NULL, &in, NULL);
21
22         execlp(pager, pager, NULL);
23         execl("/bin/sh", "sh", "-c", pager, NULL);
24 }
25
26 void setup_pager(void)
27 {
28         pid_t pid;
29         int fd[2];
30         const char *pager = getenv("GIT_PAGER");
31
32         if (!isatty(1))
33                 return;
34         if (!pager) {
35                 if (!pager_program)
36                         git_config(git_default_config);
37                 pager = pager_program;
38         }
39         if (!pager)
40                 pager = getenv("PAGER");
41         if (!pager)
42                 pager = "less";
43         else if (!*pager || !strcmp(pager, "cat"))
44                 return;
45
46         spawned_pager = 1; /* means we are emitting to terminal */
47
48         if (pipe(fd) < 0)
49                 return;
50         pid = fork();
51         if (pid < 0) {
52                 close(fd[0]);
53                 close(fd[1]);
54                 return;
55         }
56
57         /* return in the child */
58         if (!pid) {
59                 dup2(fd[1], 1);
60                 dup2(fd[1], 2);
61                 close(fd[0]);
62                 close(fd[1]);
63                 return;
64         }
65
66         /* The original process turns into the PAGER */
67         dup2(fd[0], 0);
68         close(fd[0]);
69         close(fd[1]);
70
71         setenv("LESS", "FRSX", 0);
72         run_pager(pager);
73         die("unable to execute pager '%s'", pager);
74         exit(255);
75 }
76
77 int pager_in_use(void)
78 {
79         const char *env;
80
81         if (spawned_pager)
82                 return 1;
83
84         env = getenv("GIT_PAGER_IN_USE");
85         return env ? git_config_bool("GIT_PAGER_IN_USE", env) : 0;
86 }