pager.con commit builtin-help: make some internal functions available to other builtins (940208a)
   1#include "cache.h"
   2
   3/*
   4 * This is split up from the rest of git so that we can do
   5 * something different on Windows.
   6 */
   7
   8static int spawned_pager;
   9
  10#ifndef __MINGW32__
  11static void run_pager(const char *pager)
  12{
  13        /*
  14         * Work around bug in "less" by not starting it until we
  15         * have real input
  16         */
  17        fd_set in;
  18
  19        FD_ZERO(&in);
  20        FD_SET(0, &in);
  21        select(1, &in, NULL, &in, NULL);
  22
  23        execlp(pager, pager, NULL);
  24        execl("/bin/sh", "sh", "-c", pager, NULL);
  25}
  26#else
  27#include "run-command.h"
  28
  29static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
  30static struct child_process pager_process = {
  31        .argv = pager_argv,
  32        .in = -1
  33};
  34static void wait_for_pager(void)
  35{
  36        fflush(stdout);
  37        fflush(stderr);
  38        /* signal EOF to pager */
  39        close(1);
  40        close(2);
  41        finish_command(&pager_process);
  42}
  43#endif
  44
  45void setup_pager(void)
  46{
  47#ifndef __MINGW32__
  48        pid_t pid;
  49        int fd[2];
  50#endif
  51        const char *pager = getenv("GIT_PAGER");
  52
  53        if (!isatty(1))
  54                return;
  55        if (!pager) {
  56                if (!pager_program)
  57                        git_config(git_default_config, NULL);
  58                pager = pager_program;
  59        }
  60        if (!pager)
  61                pager = getenv("PAGER");
  62        if (!pager)
  63                pager = "less";
  64        else if (!*pager || !strcmp(pager, "cat"))
  65                return;
  66
  67        spawned_pager = 1; /* means we are emitting to terminal */
  68
  69#ifndef __MINGW32__
  70        if (pipe(fd) < 0)
  71                return;
  72        pid = fork();
  73        if (pid < 0) {
  74                close(fd[0]);
  75                close(fd[1]);
  76                return;
  77        }
  78
  79        /* return in the child */
  80        if (!pid) {
  81                dup2(fd[1], 1);
  82                dup2(fd[1], 2);
  83                close(fd[0]);
  84                close(fd[1]);
  85                return;
  86        }
  87
  88        /* The original process turns into the PAGER */
  89        dup2(fd[0], 0);
  90        close(fd[0]);
  91        close(fd[1]);
  92
  93        setenv("LESS", "FRSX", 0);
  94        run_pager(pager);
  95        die("unable to execute pager '%s'", pager);
  96        exit(255);
  97#else
  98        /* spawn the pager */
  99        pager_argv[2] = pager;
 100        if (start_command(&pager_process))
 101                return;
 102
 103        /* original process continues, but writes to the pipe */
 104        dup2(pager_process.in, 1);
 105        dup2(pager_process.in, 2);
 106        close(pager_process.in);
 107
 108        /* this makes sure that the parent terminates after the pager */
 109        atexit(wait_for_pager);
 110#endif
 111}
 112
 113int pager_in_use(void)
 114{
 115        const char *env;
 116
 117        if (spawned_pager)
 118                return 1;
 119
 120        env = getenv("GIT_PAGER_IN_USE");
 121        return env ? git_config_bool("GIT_PAGER_IN_USE", env) : 0;
 122}