Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Apr 14-17, 2025
Register
Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2#include <sys/select.h>
  3#include <stdlib.h>
  4#include <stdio.h>
  5#include <string.h>
  6#include <signal.h>
  7#include <sys/ioctl.h>
  8#include "pager.h"
  9#include "run-command.h"
 10#include "sigchain.h"
 11#include "subcmd-config.h"
 12
 13/*
 14 * This is split up from the rest of git so that we can do
 15 * something different on Windows.
 16 */
 17
 18static int spawned_pager;
 19static int pager_columns;
 20
 21void pager_init(const char *pager_env)
 22{
 23	subcmd_config.pager_env = pager_env;
 24}
 25
 26static const char *forced_pager;
 27
 28void force_pager(const char *pager)
 29{
 30	forced_pager = pager;
 31}
 32
 33static void pager_preexec(void)
 34{
 35	/*
 36	 * Work around bug in "less" by not starting it until we
 37	 * have real input
 38	 */
 39	fd_set in;
 40	fd_set exception;
 41
 42	FD_ZERO(&in);
 43	FD_ZERO(&exception);
 44	FD_SET(0, &in);
 45	FD_SET(0, &exception);
 46	select(1, &in, NULL, &exception, NULL);
 47
 48	setenv("LESS", "FRSX", 0);
 49}
 50
 51static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
 52static struct child_process pager_process;
 53
 54static void wait_for_pager(void)
 55{
 56	fflush(stdout);
 57	fflush(stderr);
 58	/* signal EOF to pager */
 59	close(1);
 60	close(2);
 61	finish_command(&pager_process);
 62}
 63
 64static void wait_for_pager_signal(int signo)
 65{
 66	wait_for_pager();
 67	sigchain_pop(signo);
 68	raise(signo);
 69}
 70
 71void setup_pager(void)
 72{
 73	const char *pager = getenv(subcmd_config.pager_env);
 74	struct winsize sz;
 75
 76	if (forced_pager)
 77		pager = forced_pager;
 78	if (!isatty(1) && !forced_pager)
 79		return;
 80	if (ioctl(1, TIOCGWINSZ, &sz) == 0)
 81		pager_columns = sz.ws_col;
 82	if (!pager)
 83		pager = getenv("PAGER");
 84	if (!(pager || access("/usr/bin/pager", X_OK)))
 85		pager = "/usr/bin/pager";
 86	if (!(pager || access("/usr/bin/less", X_OK)))
 87		pager = "/usr/bin/less";
 88	if (!pager)
 89		pager = "cat";
 90	if (!*pager || !strcmp(pager, "cat"))
 91		return;
 92
 93	spawned_pager = 1; /* means we are emitting to terminal */
 94
 95	/* spawn the pager */
 96	pager_argv[2] = pager;
 97	pager_process.argv = pager_argv;
 98	pager_process.in = -1;
 99	pager_process.preexec_cb = pager_preexec;
100
101	if (start_command(&pager_process))
102		return;
103
104	/* original process continues, but writes to the pipe */
105	dup2(pager_process.in, 1);
106	if (isatty(2))
107		dup2(pager_process.in, 2);
108	close(pager_process.in);
109
110	/* this makes sure that the parent terminates after the pager */
111	sigchain_push_common(wait_for_pager_signal);
112	atexit(wait_for_pager);
113}
114
115int pager_in_use(void)
116{
117	return spawned_pager;
118}
119
120int pager_get_columns(void)
121{
122	char *s;
123
124	s = getenv("COLUMNS");
125	if (s)
126		return atoi(s);
127
128	return (pager_columns ? pager_columns : 80) - 2;
129}
v4.10.11
 
  1#include <sys/select.h>
  2#include <stdlib.h>
  3#include <stdio.h>
  4#include <string.h>
  5#include <signal.h>
  6#include <sys/ioctl.h>
  7#include "pager.h"
  8#include "run-command.h"
  9#include "sigchain.h"
 10#include "subcmd-config.h"
 11
 12/*
 13 * This is split up from the rest of git so that we can do
 14 * something different on Windows.
 15 */
 16
 17static int spawned_pager;
 18static int pager_columns;
 19
 20void pager_init(const char *pager_env)
 21{
 22	subcmd_config.pager_env = pager_env;
 23}
 24
 
 
 
 
 
 
 
 25static void pager_preexec(void)
 26{
 27	/*
 28	 * Work around bug in "less" by not starting it until we
 29	 * have real input
 30	 */
 31	fd_set in;
 
 32
 33	FD_ZERO(&in);
 
 34	FD_SET(0, &in);
 35	select(1, &in, NULL, &in, NULL);
 
 36
 37	setenv("LESS", "FRSX", 0);
 38}
 39
 40static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
 41static struct child_process pager_process;
 42
 43static void wait_for_pager(void)
 44{
 45	fflush(stdout);
 46	fflush(stderr);
 47	/* signal EOF to pager */
 48	close(1);
 49	close(2);
 50	finish_command(&pager_process);
 51}
 52
 53static void wait_for_pager_signal(int signo)
 54{
 55	wait_for_pager();
 56	sigchain_pop(signo);
 57	raise(signo);
 58}
 59
 60void setup_pager(void)
 61{
 62	const char *pager = getenv(subcmd_config.pager_env);
 63	struct winsize sz;
 64
 65	if (!isatty(1))
 
 
 66		return;
 67	if (ioctl(1, TIOCGWINSZ, &sz) == 0)
 68		pager_columns = sz.ws_col;
 69	if (!pager)
 70		pager = getenv("PAGER");
 71	if (!(pager || access("/usr/bin/pager", X_OK)))
 72		pager = "/usr/bin/pager";
 73	if (!(pager || access("/usr/bin/less", X_OK)))
 74		pager = "/usr/bin/less";
 75	if (!pager)
 76		pager = "cat";
 77	if (!*pager || !strcmp(pager, "cat"))
 78		return;
 79
 80	spawned_pager = 1; /* means we are emitting to terminal */
 81
 82	/* spawn the pager */
 83	pager_argv[2] = pager;
 84	pager_process.argv = pager_argv;
 85	pager_process.in = -1;
 86	pager_process.preexec_cb = pager_preexec;
 87
 88	if (start_command(&pager_process))
 89		return;
 90
 91	/* original process continues, but writes to the pipe */
 92	dup2(pager_process.in, 1);
 93	if (isatty(2))
 94		dup2(pager_process.in, 2);
 95	close(pager_process.in);
 96
 97	/* this makes sure that the parent terminates after the pager */
 98	sigchain_push_common(wait_for_pager_signal);
 99	atexit(wait_for_pager);
100}
101
102int pager_in_use(void)
103{
104	return spawned_pager;
105}
106
107int pager_get_columns(void)
108{
109	char *s;
110
111	s = getenv("COLUMNS");
112	if (s)
113		return atoi(s);
114
115	return (pager_columns ? pager_columns : 80) - 2;
116}