Merge branch 'master' of http://repo.or.cz/r/msysgit into devel
[msysgit/historical-msysgit.git] / git / pager.c
blob13d99d882fc78b9bf3ec96a9aaf0d47c3c4b5764
1 #include "cache.h"
2 #include "spawn-pipe.h"
4 /*
5 * This is split up from the rest of git so that we might do
6 * something different on Windows, for example.
7 */
9 #ifndef __MINGW32__
10 static void run_pager(const char *pager)
13 * Work around bug in "less" by not starting it until we
14 * have real input
16 fd_set in;
18 FD_ZERO(&in);
19 FD_SET(0, &in);
20 select(1, &in, NULL, &in, NULL);
22 execlp(pager, pager, NULL);
23 execl("/bin/sh", "sh", "-c", pager, NULL);
25 #else
26 static pid_t pager_pid;
27 static void collect_pager(void)
29 fflush(stdout);
30 close(1); /* signals EOF to pager */
31 cwait(NULL, pager_pid, 0);
33 #endif
35 void setup_pager(void)
37 #ifndef __MINGW32__
38 pid_t pid;
39 #else
40 const char *pager_argv[] = { "sh", "-c", NULL, NULL };
41 #endif
42 int fd[2];
43 const char *pager = getenv("GIT_PAGER");
45 if (!isatty(1))
46 return;
47 if (!pager)
48 pager = pager_program;
49 if (!pager)
50 pager = getenv("PAGER");
51 if (!pager)
52 pager = "less";
53 else if (!*pager || !strcmp(pager, "cat"))
54 return;
56 pager_in_use = 1; /* means we are emitting to terminal */
58 if (pipe(fd) < 0)
59 return;
60 #ifndef __MINGW32__
61 pid = fork();
62 if (pid < 0) {
63 close(fd[0]);
64 close(fd[1]);
65 return;
68 /* return in the child */
69 if (!pid) {
70 dup2(fd[1], 1);
71 close(fd[0]);
72 close(fd[1]);
73 return;
76 /* The original process turns into the PAGER */
77 dup2(fd[0], 0);
78 close(fd[0]);
79 close(fd[1]);
81 setenv("LESS", "FRSX", 0);
82 run_pager(pager);
83 die("unable to execute pager '%s'", pager);
84 exit(255);
85 #else
86 /* spawn the pager */
87 pager_argv[2] = pager;
88 pager_pid = spawnvpe_pipe(pager_argv[0], pager_argv, environ, fd, NULL);
89 if (pager_pid < 0)
90 return;
92 /* original process continues, but writes to the pipe */
93 dup2(fd[1], 1);
94 close(fd[1]);
96 /* this makes sure that the parent terminates after the pager */
97 atexit(collect_pager);
98 #endif