// SPDX-License-Identifier: GPL-2.0#include <sys/select.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <signal.h>#include <sys/ioctl.h>#include "pager.h"#include "run-command.h"#include "sigchain.h"#include "subcmd-config.h"/* * This is split up from the rest of git so that we can do * something different on Windows. */static int spawned_pager;static int pager_columns;void pager_init(const char *pager_env){ subcmd_config.pager_env = pager_env;}static const char *forced_pager;void force_pager(const char *pager){ forced_pager = pager;}static void pager_preexec(void){ /* * Work around bug in "less" by not starting it until we * have real input */ fd_set in; fd_set exception; FD_ZERO(&in); FD_ZERO(&exception); FD_SET(0, &in); FD_SET(0, &exception); select(1, &in, NULL, &exception, NULL); setenv("LESS", "FRSX", 0);}static const char *pager_argv[] = { "sh", "-c", NULL, NULL };static struct child_process pager_process;static void wait_for_pager(void){ fflush(stdout); fflush(stderr); /* signal EOF to pager */ close(1); close(2); finish_command(&pager_process);}static void wait_for_pager_signal(int signo){ wait_for_pager(); sigchain_pop(signo); raise(signo);}void setup_pager(void){ const char *pager = getenv(subcmd_config.pager_env); struct winsize sz; if (forced_pager) pager = forced_pager; if (!isatty(1) && !forced_pager) return; if (ioctl(1, TIOCGWINSZ, &sz) == 0) pager_columns = sz.ws_col; if (!pager) pager = getenv("PAGER"); if (!(pager || access("/usr/bin/pager", X_OK))) pager = "/usr/bin/pager"; if (!(pager || access("/usr/bin/less", X_OK))) pager = "/usr/bin/less"; if (!pager) pager = "cat"; if (!*pager || !strcmp(pager, "cat")) return; spawned_pager = 1; /* means we are emitting to terminal */ /* spawn the pager */ pager_argv[2] = pager; pager_process.argv = pager_argv; pager_process.in = -1; pager_process.preexec_cb = pager_preexec; if (start_command(&pager_process)) return; /* original process continues, but writes to the pipe */ dup2(pager_process.in, 1); if (isatty(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);}int pager_in_use(void){ return spawned_pager;}int pager_get_columns(void){ char *s; s = getenv("COLUMNS"); if (s) return atoi(s); return (pager_columns ? pager_columns : 80) - 2;}
// SPDX-License-Identifier: GPL-2.0
#include <sys/select.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/ioctl.h>
#include "pager.h"
#include "run-command.h"
#include "sigchain.h"
#include "subcmd-config.h"
/*
* This is split up from the rest of git so that we can do
* something different on Windows.
*/
static int spawned_pager;
static int pager_columns;
void pager_init(const char *pager_env)
{
subcmd_config.pager_env = pager_env;
}
static const char *forced_pager;
void force_pager(const char *pager)
{
forced_pager = pager;
}
static void pager_preexec(void)
{
/*
* Work around bug in "less" by not starting it until we
* have real input
*/
fd_set in;
fd_set exception;
FD_ZERO(&in);
FD_ZERO(&exception);
FD_SET(0, &in);
FD_SET(0, &exception);
select(1, &in, NULL, &exception, NULL);
setenv("LESS", "FRSX", 0);
}
static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
static struct child_process pager_process;
static void wait_for_pager(void)
{
fflush(stdout);
fflush(stderr);
/* signal EOF to pager */
close(1);
close(2);
finish_command(&pager_process);
}
static void wait_for_pager_signal(int signo)
{
wait_for_pager();
sigchain_pop(signo);
raise(signo);
}
void setup_pager(void)
{
const char *pager = getenv(subcmd_config.pager_env);
struct winsize sz;
if (forced_pager)
pager = forced_pager;
if (!isatty(1) && !forced_pager)
return;
if (ioctl(1, TIOCGWINSZ, &sz) == 0)
pager_columns = sz.ws_col;
if (!pager)
pager = getenv("PAGER");
if (!(pager || access("/usr/bin/pager", X_OK)))
pager = "/usr/bin/pager";
if (!(pager || access("/usr/bin/less", X_OK)))
pager = "/usr/bin/less";
if (!pager)
pager = "cat";
if (!*pager || !strcmp(pager, "cat"))
return;
spawned_pager = 1; /* means we are emitting to terminal */
/* spawn the pager */
pager_argv[2] = pager;
pager_process.argv = pager_argv;
pager_process.in = -1;
pager_process.preexec_cb = pager_preexec;
if (start_command(&pager_process))
return;
/* original process continues, but writes to the pipe */
dup2(pager_process.in, 1);
if (isatty(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);
}
int pager_in_use(void)
{
return spawned_pager;
}
int pager_get_columns(void)
{
char *s;
s = getenv("COLUMNS");
if (s)
return atoi(s);
return (pager_columns ? pager_columns : 80) - 2;
}