aboutsummaryrefslogtreecommitdiffstats
path: root/pager.c
diff options
context:
space:
mode:
Diffstat (limited to 'pager.c')
-rw-r--r--pager.c72
1 files changed, 58 insertions, 14 deletions
diff --git a/pager.c b/pager.c
index 63055d0873..5531fff50e 100644
--- a/pager.c
+++ b/pager.c
@@ -13,7 +13,8 @@ int pager_use_color = 1;
#endif
static struct child_process pager_process;
-static const char *pager_program;
+static char *pager_program;
+static int old_fd1 = -1, old_fd2 = -1;
/* Is the value coming back from term_columns() just a guess? */
static int term_columns_guessed;
@@ -23,10 +24,11 @@ static void close_pager_fds(void)
{
/* signal EOF to pager */
close(1);
- close(2);
+ if (old_fd2 != -1)
+ close(2);
}
-static void wait_for_pager_atexit(void)
+static void finish_pager(void)
{
fflush(stdout);
fflush(stderr);
@@ -34,8 +36,37 @@ static void wait_for_pager_atexit(void)
finish_command(&pager_process);
}
+static void wait_for_pager_atexit(void)
+{
+ if (old_fd1 == -1)
+ return;
+
+ finish_pager();
+}
+
+void wait_for_pager(void)
+{
+ if (old_fd1 == -1)
+ return;
+
+ finish_pager();
+ sigchain_pop_common();
+ unsetenv("GIT_PAGER_IN_USE");
+ dup2(old_fd1, 1);
+ close(old_fd1);
+ old_fd1 = -1;
+ if (old_fd2 != -1) {
+ dup2(old_fd2, 2);
+ close(old_fd2);
+ old_fd2 = -1;
+ }
+}
+
static void wait_for_pager_signal(int signo)
{
+ if (old_fd1 == -1)
+ return;
+
close_pager_fds();
finish_command_in_signal(&pager_process);
sigchain_pop(signo);
@@ -43,6 +74,7 @@ static void wait_for_pager_signal(int signo)
}
static int core_pager_config(const char *var, const char *value,
+ const struct config_context *ctx UNUSED,
void *data UNUSED)
{
if (!strcmp(var, "core.pager"))
@@ -50,7 +82,7 @@ static int core_pager_config(const char *var, const char *value,
return 0;
}
-const char *git_pager(int stdout_is_tty)
+const char *git_pager(struct repository *r, int stdout_is_tty)
{
const char *pager;
@@ -60,7 +92,8 @@ const char *git_pager(int stdout_is_tty)
pager = getenv("GIT_PAGER");
if (!pager) {
if (!pager_program)
- read_early_config(core_pager_config, NULL);
+ read_early_config(r,
+ core_pager_config, NULL);
pager = pager_program;
}
if (!pager)
@@ -108,9 +141,10 @@ void prepare_pager_args(struct child_process *pager_process, const char *pager)
pager_process->trace2_child_class = "pager";
}
-void setup_pager(void)
+void setup_pager(struct repository *r)
{
- const char *pager = git_pager(isatty(1));
+ static int once = 0;
+ const char *pager = git_pager(r, isatty(1));
if (!pager)
return;
@@ -136,17 +170,23 @@ void setup_pager(void)
pager_process.in = -1;
strvec_push(&pager_process.env, "GIT_PAGER_IN_USE");
if (start_command(&pager_process))
- return;
+ die("unable to execute pager '%s'", pager);
/* original process continues, but writes to the pipe */
+ old_fd1 = dup(1);
dup2(pager_process.in, 1);
- if (isatty(2))
+ if (isatty(2)) {
+ old_fd2 = dup(2);
dup2(pager_process.in, 2);
+ }
close(pager_process.in);
- /* this makes sure that the parent terminates after the pager */
sigchain_push_common(wait_for_pager_signal);
- atexit(wait_for_pager_atexit);
+
+ if (!once) {
+ once++;
+ atexit(wait_for_pager_atexit);
+ }
}
int pager_in_use(void)
@@ -195,6 +235,8 @@ int term_columns(void)
*/
void term_clear_line(void)
{
+ if (!isatty(2))
+ return;
if (is_terminal_dumb())
/*
* Fall back to print a terminal width worth of space
@@ -228,7 +270,9 @@ struct pager_command_config_data {
char *value;
};
-static int pager_command_config(const char *var, const char *value, void *vdata)
+static int pager_command_config(const char *var, const char *value,
+ const struct config_context *ctx UNUSED,
+ void *vdata)
{
struct pager_command_config_data *data = vdata;
const char *cmd;
@@ -247,7 +291,7 @@ static int pager_command_config(const char *var, const char *value, void *vdata)
}
/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
-int check_pager_config(const char *cmd)
+int check_pager_config(struct repository *r, const char *cmd)
{
struct pager_command_config_data data;
@@ -255,7 +299,7 @@ int check_pager_config(const char *cmd)
data.want = -1;
data.value = NULL;
- read_early_config(pager_command_config, &data);
+ read_early_config(r, pager_command_config, &data);
if (data.value)
pager_program = data.value;