Merge git://git.kernel.org/pub/scm/gitk/gitk
[git/jrn.git] / pager.c
blob6b5c9e44b4ded338ddb344ae454d83a685b7569a
1 #include "cache.h"
3 /*
4 * This is split up from the rest of git so that we can do
5 * something different on Windows.
6 */
8 static int spawned_pager;
10 #ifndef __MINGW32__
11 static void run_pager(const char *pager)
14 * Work around bug in "less" by not starting it until we
15 * have real input
17 fd_set in;
19 FD_ZERO(&in);
20 FD_SET(0, &in);
21 select(1, &in, NULL, &in, NULL);
23 execlp(pager, pager, NULL);
24 execl("/bin/sh", "sh", "-c", pager, NULL);
26 #else
27 #include "run-command.h"
29 static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
30 static struct child_process pager_process = {
31 .argv = pager_argv,
32 .in = -1
34 static void wait_for_pager(void)
36 fflush(stdout);
37 fflush(stderr);
38 /* signal EOF to pager */
39 close(1);
40 close(2);
41 finish_command(&pager_process);
43 #endif
45 void setup_pager(void)
47 #ifndef __MINGW32__
48 pid_t pid;
49 int fd[2];
50 #endif
51 const char *pager = getenv("GIT_PAGER");
53 if (!isatty(1))
54 return;
55 if (!pager) {
56 if (!pager_program)
57 git_config(git_default_config, NULL);
58 pager = pager_program;
60 if (!pager)
61 pager = getenv("PAGER");
62 if (!pager)
63 pager = "less";
64 else if (!*pager || !strcmp(pager, "cat"))
65 return;
67 spawned_pager = 1; /* means we are emitting to terminal */
69 #ifndef __MINGW32__
70 if (pipe(fd) < 0)
71 return;
72 pid = fork();
73 if (pid < 0) {
74 close(fd[0]);
75 close(fd[1]);
76 return;
79 /* return in the child */
80 if (!pid) {
81 dup2(fd[1], 1);
82 dup2(fd[1], 2);
83 close(fd[0]);
84 close(fd[1]);
85 return;
88 /* The original process turns into the PAGER */
89 dup2(fd[0], 0);
90 close(fd[0]);
91 close(fd[1]);
93 setenv("LESS", "FRSX", 0);
94 run_pager(pager);
95 die("unable to execute pager '%s'", pager);
96 exit(255);
97 #else
98 /* spawn the pager */
99 pager_argv[2] = pager;
100 if (start_command(&pager_process))
101 return;
103 /* original process continues, but writes to the pipe */
104 dup2(pager_process.in, 1);
105 dup2(pager_process.in, 2);
106 close(pager_process.in);
108 /* this makes sure that the parent terminates after the pager */
109 atexit(wait_for_pager);
110 #endif
113 int pager_in_use(void)
115 const char *env;
117 if (spawned_pager)
118 return 1;
120 env = getenv("GIT_PAGER_IN_USE");
121 return env ? git_config_bool("GIT_PAGER_IN_USE", env) : 0;