Linux Audio

Check our new training course

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