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