Merge branch 'jc/cachetree' into cr/reset
[git] / pager.c
1 #include "cache.h"
2
3 #include <sys/select.h>
4
5 /*
6  * This is split up from the rest of git so that we might do
7  * something different on Windows, for example.
8  */
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         pager_in_use = 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                 close(fd[0]);
61                 close(fd[1]);
62                 return;
63         }
64
65         /* The original process turns into the PAGER */
66         dup2(fd[0], 0);
67         close(fd[0]);
68         close(fd[1]);
69
70         setenv("LESS", "FRSX", 0);
71         run_pager(pager);
72         die("unable to execute pager '%s'", pager);
73         exit(255);
74 }