0001
0002 #include <sys/select.h>
0003 #include <stdlib.h>
0004 #include <stdio.h>
0005 #include <string.h>
0006 #include <signal.h>
0007 #include <sys/ioctl.h>
0008 #include "pager.h"
0009 #include "run-command.h"
0010 #include "sigchain.h"
0011 #include "subcmd-config.h"
0012
0013
0014
0015
0016
0017
0018 static int spawned_pager;
0019 static int pager_columns;
0020
0021 void pager_init(const char *pager_env)
0022 {
0023 subcmd_config.pager_env = pager_env;
0024 }
0025
0026 static const char *forced_pager;
0027
0028 void force_pager(const char *pager)
0029 {
0030 forced_pager = pager;
0031 }
0032
0033 static void pager_preexec(void)
0034 {
0035
0036
0037
0038
0039 fd_set in;
0040 fd_set exception;
0041
0042 FD_ZERO(&in);
0043 FD_ZERO(&exception);
0044 FD_SET(0, &in);
0045 FD_SET(0, &exception);
0046 select(1, &in, NULL, &exception, NULL);
0047
0048 setenv("LESS", "FRSX", 0);
0049 }
0050
0051 static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
0052 static struct child_process pager_process;
0053
0054 static void wait_for_pager(void)
0055 {
0056 fflush(stdout);
0057 fflush(stderr);
0058
0059 close(1);
0060 close(2);
0061 finish_command(&pager_process);
0062 }
0063
0064 static void wait_for_pager_signal(int signo)
0065 {
0066 wait_for_pager();
0067 sigchain_pop(signo);
0068 raise(signo);
0069 }
0070
0071 void setup_pager(void)
0072 {
0073 const char *pager = getenv(subcmd_config.pager_env);
0074 struct winsize sz;
0075
0076 if (forced_pager)
0077 pager = forced_pager;
0078 if (!isatty(1) && !forced_pager)
0079 return;
0080 if (ioctl(1, TIOCGWINSZ, &sz) == 0)
0081 pager_columns = sz.ws_col;
0082 if (!pager)
0083 pager = getenv("PAGER");
0084 if (!(pager || access("/usr/bin/pager", X_OK)))
0085 pager = "/usr/bin/pager";
0086 if (!(pager || access("/usr/bin/less", X_OK)))
0087 pager = "/usr/bin/less";
0088 if (!pager)
0089 pager = "cat";
0090 if (!*pager || !strcmp(pager, "cat"))
0091 return;
0092
0093 spawned_pager = 1;
0094
0095
0096 pager_argv[2] = pager;
0097 pager_process.argv = pager_argv;
0098 pager_process.in = -1;
0099 pager_process.preexec_cb = pager_preexec;
0100
0101 if (start_command(&pager_process))
0102 return;
0103
0104
0105 dup2(pager_process.in, 1);
0106 if (isatty(2))
0107 dup2(pager_process.in, 2);
0108 close(pager_process.in);
0109
0110
0111 sigchain_push_common(wait_for_pager_signal);
0112 atexit(wait_for_pager);
0113 }
0114
0115 int pager_in_use(void)
0116 {
0117 return spawned_pager;
0118 }
0119
0120 int pager_get_columns(void)
0121 {
0122 char *s;
0123
0124 s = getenv("COLUMNS");
0125 if (s)
0126 return atoi(s);
0127
0128 return (pager_columns ? pager_columns : 80) - 2;
0129 }