1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * Pager: Routines to create a "more" running out of a particular file
3*6a54128fSAndroid Build Coastguard Worker * descriptor.
4*6a54128fSAndroid Build Coastguard Worker *
5*6a54128fSAndroid Build Coastguard Worker * Copyright 1987, 1988 by MIT Student Information Processing Board
6*6a54128fSAndroid Build Coastguard Worker *
7*6a54128fSAndroid Build Coastguard Worker * Permission to use, copy, modify, and distribute this software and
8*6a54128fSAndroid Build Coastguard Worker * its documentation for any purpose is hereby granted, provided that
9*6a54128fSAndroid Build Coastguard Worker * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
10*6a54128fSAndroid Build Coastguard Worker * advertising or publicity pertaining to distribution of the software
11*6a54128fSAndroid Build Coastguard Worker * without specific, written prior permission. M.I.T. and the
12*6a54128fSAndroid Build Coastguard Worker * M.I.T. S.I.P.B. make no representations about the suitability of
13*6a54128fSAndroid Build Coastguard Worker * this software for any purpose. It is provided "as is" without
14*6a54128fSAndroid Build Coastguard Worker * express or implied warranty.
15*6a54128fSAndroid Build Coastguard Worker */
16*6a54128fSAndroid Build Coastguard Worker
17*6a54128fSAndroid Build Coastguard Worker #include "config.h"
18*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_UNISTD_H
19*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
20*6a54128fSAndroid Build Coastguard Worker #endif
21*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_ERRNO_H
22*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
23*6a54128fSAndroid Build Coastguard Worker #endif
24*6a54128fSAndroid Build Coastguard Worker
25*6a54128fSAndroid Build Coastguard Worker #include "ss_internal.h"
26*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
27*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
28*6a54128fSAndroid Build Coastguard Worker #include <sys/file.h>
29*6a54128fSAndroid Build Coastguard Worker #include <signal.h>
30*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_PRCTL_H
31*6a54128fSAndroid Build Coastguard Worker #include <sys/prctl.h>
32*6a54128fSAndroid Build Coastguard Worker #else
33*6a54128fSAndroid Build Coastguard Worker #define PR_GET_DUMPABLE 3
34*6a54128fSAndroid Build Coastguard Worker #endif
35*6a54128fSAndroid Build Coastguard Worker #if (!defined(HAVE_PRCTL) && defined(linux))
36*6a54128fSAndroid Build Coastguard Worker #include <sys/syscall.h>
37*6a54128fSAndroid Build Coastguard Worker #endif
38*6a54128fSAndroid Build Coastguard Worker
39*6a54128fSAndroid Build Coastguard Worker static char MORE[] = "more";
40*6a54128fSAndroid Build Coastguard Worker extern char *getenv PROTOTYPE((const char *));
41*6a54128fSAndroid Build Coastguard Worker
ss_safe_getenv(const char * arg)42*6a54128fSAndroid Build Coastguard Worker char *ss_safe_getenv(const char *arg)
43*6a54128fSAndroid Build Coastguard Worker {
44*6a54128fSAndroid Build Coastguard Worker if ((getuid() != geteuid()) || (getgid() != getegid()))
45*6a54128fSAndroid Build Coastguard Worker return NULL;
46*6a54128fSAndroid Build Coastguard Worker #if HAVE_PRCTL
47*6a54128fSAndroid Build Coastguard Worker if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
48*6a54128fSAndroid Build Coastguard Worker return NULL;
49*6a54128fSAndroid Build Coastguard Worker #else
50*6a54128fSAndroid Build Coastguard Worker #if (defined(linux) && defined(SYS_prctl))
51*6a54128fSAndroid Build Coastguard Worker if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
52*6a54128fSAndroid Build Coastguard Worker return NULL;
53*6a54128fSAndroid Build Coastguard Worker #endif
54*6a54128fSAndroid Build Coastguard Worker #endif
55*6a54128fSAndroid Build Coastguard Worker
56*6a54128fSAndroid Build Coastguard Worker #if defined(HAVE_SECURE_GETENV)
57*6a54128fSAndroid Build Coastguard Worker return secure_getenv(arg);
58*6a54128fSAndroid Build Coastguard Worker #elif defined(HAVE___SECURE_GETENV)
59*6a54128fSAndroid Build Coastguard Worker return __secure_getenv(arg);
60*6a54128fSAndroid Build Coastguard Worker #else
61*6a54128fSAndroid Build Coastguard Worker return getenv(arg);
62*6a54128fSAndroid Build Coastguard Worker #endif
63*6a54128fSAndroid Build Coastguard Worker }
64*6a54128fSAndroid Build Coastguard Worker
65*6a54128fSAndroid Build Coastguard Worker /*
66*6a54128fSAndroid Build Coastguard Worker * this needs a *lot* of work....
67*6a54128fSAndroid Build Coastguard Worker *
68*6a54128fSAndroid Build Coastguard Worker * run in same process
69*6a54128fSAndroid Build Coastguard Worker * handle SIGINT sensibly
70*6a54128fSAndroid Build Coastguard Worker * allow finer control -- put-page-break-here
71*6a54128fSAndroid Build Coastguard Worker */
72*6a54128fSAndroid Build Coastguard Worker
73*6a54128fSAndroid Build Coastguard Worker #ifndef NO_FORK
ss_pager_create(void)74*6a54128fSAndroid Build Coastguard Worker int ss_pager_create(void)
75*6a54128fSAndroid Build Coastguard Worker {
76*6a54128fSAndroid Build Coastguard Worker int filedes[2];
77*6a54128fSAndroid Build Coastguard Worker
78*6a54128fSAndroid Build Coastguard Worker if (pipe(filedes) != 0)
79*6a54128fSAndroid Build Coastguard Worker return(-1);
80*6a54128fSAndroid Build Coastguard Worker
81*6a54128fSAndroid Build Coastguard Worker switch(fork()) {
82*6a54128fSAndroid Build Coastguard Worker case -1:
83*6a54128fSAndroid Build Coastguard Worker return(-1);
84*6a54128fSAndroid Build Coastguard Worker case 0:
85*6a54128fSAndroid Build Coastguard Worker /*
86*6a54128fSAndroid Build Coastguard Worker * Child; dup read half to 0, close all but 0, 1, and 2
87*6a54128fSAndroid Build Coastguard Worker */
88*6a54128fSAndroid Build Coastguard Worker if (dup2(filedes[0], 0) == -1)
89*6a54128fSAndroid Build Coastguard Worker exit(1);
90*6a54128fSAndroid Build Coastguard Worker ss_page_stdin();
91*6a54128fSAndroid Build Coastguard Worker default:
92*6a54128fSAndroid Build Coastguard Worker /*
93*6a54128fSAndroid Build Coastguard Worker * Parent: close "read" side of pipe, return
94*6a54128fSAndroid Build Coastguard Worker * "write" side.
95*6a54128fSAndroid Build Coastguard Worker */
96*6a54128fSAndroid Build Coastguard Worker (void) close(filedes[0]);
97*6a54128fSAndroid Build Coastguard Worker return(filedes[1]);
98*6a54128fSAndroid Build Coastguard Worker }
99*6a54128fSAndroid Build Coastguard Worker }
100*6a54128fSAndroid Build Coastguard Worker #else /* don't fork */
ss_pager_create()101*6a54128fSAndroid Build Coastguard Worker int ss_pager_create()
102*6a54128fSAndroid Build Coastguard Worker {
103*6a54128fSAndroid Build Coastguard Worker int fd;
104*6a54128fSAndroid Build Coastguard Worker fd = open("/dev/tty", O_WRONLY, 0);
105*6a54128fSAndroid Build Coastguard Worker return fd;
106*6a54128fSAndroid Build Coastguard Worker }
107*6a54128fSAndroid Build Coastguard Worker #endif
108*6a54128fSAndroid Build Coastguard Worker
write_all(int fd,char * buf,size_t count)109*6a54128fSAndroid Build Coastguard Worker static int write_all(int fd, char *buf, size_t count)
110*6a54128fSAndroid Build Coastguard Worker {
111*6a54128fSAndroid Build Coastguard Worker ssize_t ret;
112*6a54128fSAndroid Build Coastguard Worker int c = 0;
113*6a54128fSAndroid Build Coastguard Worker
114*6a54128fSAndroid Build Coastguard Worker while (count > 0) {
115*6a54128fSAndroid Build Coastguard Worker ret = write(fd, buf, count);
116*6a54128fSAndroid Build Coastguard Worker if (ret < 0) {
117*6a54128fSAndroid Build Coastguard Worker if ((errno == EAGAIN) || (errno == EINTR))
118*6a54128fSAndroid Build Coastguard Worker continue;
119*6a54128fSAndroid Build Coastguard Worker return -1;
120*6a54128fSAndroid Build Coastguard Worker }
121*6a54128fSAndroid Build Coastguard Worker count -= ret;
122*6a54128fSAndroid Build Coastguard Worker buf += ret;
123*6a54128fSAndroid Build Coastguard Worker c += ret;
124*6a54128fSAndroid Build Coastguard Worker }
125*6a54128fSAndroid Build Coastguard Worker return c;
126*6a54128fSAndroid Build Coastguard Worker }
127*6a54128fSAndroid Build Coastguard Worker
ss_page_stdin(void)128*6a54128fSAndroid Build Coastguard Worker void ss_page_stdin(void)
129*6a54128fSAndroid Build Coastguard Worker {
130*6a54128fSAndroid Build Coastguard Worker int i;
131*6a54128fSAndroid Build Coastguard Worker sigset_t mask;
132*6a54128fSAndroid Build Coastguard Worker
133*6a54128fSAndroid Build Coastguard Worker for (i = 3; i < 32; i++)
134*6a54128fSAndroid Build Coastguard Worker (void) close(i);
135*6a54128fSAndroid Build Coastguard Worker (void) signal(SIGINT, SIG_DFL);
136*6a54128fSAndroid Build Coastguard Worker sigprocmask(SIG_BLOCK, 0, &mask);
137*6a54128fSAndroid Build Coastguard Worker sigdelset(&mask, SIGINT);
138*6a54128fSAndroid Build Coastguard Worker sigprocmask(SIG_SETMASK, &mask, 0);
139*6a54128fSAndroid Build Coastguard Worker if (_ss_pager_name == (char *)NULL) {
140*6a54128fSAndroid Build Coastguard Worker if ((_ss_pager_name = ss_safe_getenv("PAGER")) == (char *)NULL)
141*6a54128fSAndroid Build Coastguard Worker _ss_pager_name = MORE;
142*6a54128fSAndroid Build Coastguard Worker }
143*6a54128fSAndroid Build Coastguard Worker (void) execlp(_ss_pager_name, _ss_pager_name, (char *) NULL);
144*6a54128fSAndroid Build Coastguard Worker {
145*6a54128fSAndroid Build Coastguard Worker /* minimal recovery if pager program isn't found */
146*6a54128fSAndroid Build Coastguard Worker char buf[80];
147*6a54128fSAndroid Build Coastguard Worker register int n;
148*6a54128fSAndroid Build Coastguard Worker while ((n = read(0, buf, 80)) > 0)
149*6a54128fSAndroid Build Coastguard Worker write_all(1, buf, n);
150*6a54128fSAndroid Build Coastguard Worker }
151*6a54128fSAndroid Build Coastguard Worker exit(errno);
152*6a54128fSAndroid Build Coastguard Worker }
153