]>
Commit | Line | Data |
---|---|---|
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 |
27 | extern 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 | |
44 | static char MORE[] = "more"; | |
45 | extern char *_ss_pager_name; | |
546a1ff1 | 46 | extern char *getenv PROTOTYPE((const char *)); |
3839e657 | 47 | |
762c7c65 TT |
48 | char *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 | 80 | int 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 */ | |
107 | int ss_pager_create() | |
108 | { | |
109 | int fd; | |
110 | fd = open("/dev/tty", O_WRONLY, 0); | |
111 | return fd; | |
112 | } | |
113 | #endif | |
114 | ||
935a123f TT |
115 | static 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 |
134 | void 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 | } |