Contributors: 7
	  
        
          | Author | Tokens | Token Proportion | Commits | Commit Proportion | 
	  
	  
        
        
          | Ingo Molnar | 294 | 59.88% | 1 | 10.00% | 
        
          | Andi Kleen | 101 | 20.57% | 2 | 20.00% | 
        
          | Josh Poimboeuf | 39 | 7.94% | 3 | 30.00% | 
        
          | Michael Lentine | 21 | 4.28% | 1 | 10.00% | 
        
          | Sergey Senozhatsky | 18 | 3.67% | 1 | 10.00% | 
        
          | Avik Sil | 17 | 3.46% | 1 | 10.00% | 
        
          | Greg Kroah-Hartman | 1 | 0.20% | 1 | 10.00% | 
	  
	  
        
          | Total | 491 |  | 10 |  | 
	  
    
 
// 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;
}