Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130// 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;}