Whamcloud - gitweb
a7a2a09279dad197f962997bcf2882897aba65c5
[tools/e2fsprogs.git] / lib / ss / pager.c
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  *
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.
15  */
16
17 #ifdef HAVE_UNISTD_H
18 #include <unistd.h>
19 #endif
20 #ifdef HAVE_ERRNO_H
21 #include <errno.h>
22 #else
23 extern int errno;
24 #endif
25
26 #include "ss_internal.h"
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/file.h>
30 #include <signal.h>
31 #ifdef HAVE_SYS_PRCTL_H
32 #include <sys/prctl.h>
33 #else
34 #define PR_GET_DUMPABLE 3
35 #endif
36 #if (!defined(HAVE_PRCTL) && defined(linux))
37 #include <sys/syscall.h>
38 #endif
39
40 static char MORE[] = "more";
41 extern char *_ss_pager_name;
42 extern char *getenv PROTOTYPE((const char *));
43
44 char *ss_safe_getenv(const char *arg)
45 {
46         if ((getuid() != geteuid()) || (getgid() != getegid()))
47                 return NULL;
48 #if HAVE_PRCTL
49         if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
50                 return NULL;
51 #else
52 #if (defined(linux) && defined(SYS_prctl))
53         if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
54                 return NULL;
55 #endif
56 #endif
57
58 #ifdef HAVE___SECURE_GETENV
59         return __secure_getenv(arg);
60 #else
61         return getenv(arg);
62 #endif
63 }
64
65 /*
66  * this needs a *lot* of work....
67  *
68  * run in same process
69  * handle SIGINT sensibly
70  * allow finer control -- put-page-break-here
71  */
72
73 #ifndef NO_FORK
74 int ss_pager_create(void) 
75 {
76         int filedes[2];
77      
78         if (pipe(filedes) != 0)
79                 return(-1);
80
81         switch(fork()) {
82         case -1:
83                 return(-1);
84         case 0:
85                 /*
86                  * Child; dup read half to 0, close all but 0, 1, and 2
87                  */
88                 if (dup2(filedes[0], 0) == -1)
89                         exit(1);
90                 ss_page_stdin();
91         default:
92                 /*
93                  * Parent:  close "read" side of pipe, return
94                  * "write" side.
95                  */
96                 (void) close(filedes[0]);
97                 return(filedes[1]);
98         }
99 }
100 #else /* don't fork */
101 int ss_pager_create()
102 {
103     int fd;
104     fd = open("/dev/tty", O_WRONLY, 0);
105     return fd;
106 }
107 #endif
108
109 void ss_page_stdin()
110 {
111         int i;
112         sigset_t mask;
113         
114         for (i = 3; i < 32; i++)
115                 (void) close(i);
116         (void) signal(SIGINT, SIG_DFL);
117         sigprocmask(SIG_BLOCK, 0, &mask);
118         sigdelset(&mask, SIGINT);
119         sigprocmask(SIG_SETMASK, &mask, 0);
120         if (_ss_pager_name == (char *)NULL) {
121                 if ((_ss_pager_name = ss_safe_getenv("PAGER")) == (char *)NULL)
122                         _ss_pager_name = MORE;
123         }
124         (void) execlp(_ss_pager_name, _ss_pager_name, (char *) NULL);
125         {
126                 /* minimal recovery if pager program isn't found */
127                 char buf[80];
128                 register int n;
129                 while ((n = read(0, buf, 80)) > 0)
130                         write(1, buf, n);
131         }
132         exit(errno);
133 }