xref: /aosp_15_r20/external/e2fsprogs/lib/ss/pager.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
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