1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* util/ss/pager.c - create a "more" running out of a file descriptor */
3 /*
4 * Copyright 1987, 1988 by MIT Student Information Processing Board
5 *
6 * For copyright information, see copyright.h.
7 */
8
9 #include "ss_internal.h"
10 #include "copyright.h"
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <sys/types.h>
15 #include <sys/file.h>
16 #include <signal.h>
17
18 static char MORE[] = "more";
19 extern char *_ss_pager_name;
20
21 /*
22 * this needs a *lot* of work....
23 *
24 * run in same process
25 * handle SIGINT sensibly
26 * allow finer control -- put-page-break-here
27 */
28 void ss_page_stdin(void);
29
30 #ifndef NO_FORK
ss_pager_create(void)31 int ss_pager_create(void)
32 {
33 int filedes[2];
34
35 if (pipe(filedes) != 0)
36 return(-1);
37
38 switch((int) fork()) {
39 case -1:
40 return(-1);
41 case 0:
42 /*
43 * Child; dup read half to 0, close all but 0, 1, and 2
44 */
45 if (dup2(filedes[0], 0) == -1)
46 exit(1);
47 ss_page_stdin();
48 default:
49 /*
50 * Parent: close "read" side of pipe, return
51 * "write" side.
52 */
53 (void) close(filedes[0]);
54 set_cloexec_fd(filedes[1]);
55 return(filedes[1]);
56 }
57 }
58 #else /* don't fork */
ss_pager_create(void)59 int ss_pager_create(void)
60 {
61 int fd;
62 fd = open("/dev/tty", O_WRONLY, 0);
63 if (fd >= 0)
64 set_cloexec_fd(fd);
65 return fd;
66 }
67 #endif
68
ss_page_stdin(void)69 void ss_page_stdin(void)
70 {
71 int i;
72 #ifdef POSIX_SIGNALS
73 struct sigaction sa;
74 sigset_t mask;
75 #endif
76 for (i = 3; i < 32; i++)
77 (void) close(i);
78 #ifdef POSIX_SIGNALS
79 sa.sa_handler = SIG_DFL;
80 sigemptyset(&sa.sa_mask);
81 sa.sa_flags = 0;
82 sigaction(SIGINT, &sa, (struct sigaction *)0);
83 #else
84 (void) signal(SIGINT, SIG_DFL);
85 #endif
86 {
87 #ifdef POSIX_SIGNALS
88 sigemptyset(&mask);
89 sigaddset(&mask, SIGINT);
90 sigprocmask(SIG_UNBLOCK, &mask, (sigset_t *)0);
91 #else
92 int mask = sigblock(0);
93 mask &= ~sigmask(SIGINT);
94 sigsetmask(mask);
95 #endif
96 }
97 if (_ss_pager_name == (char *)NULL) {
98 if ((_ss_pager_name = getenv("PAGER")) == (char *)NULL)
99 _ss_pager_name = MORE;
100 }
101 (void) execlp(_ss_pager_name, _ss_pager_name, (char *) NULL);
102 {
103 /* minimal recovery if pager program isn't found */
104 char buf[80];
105 int n;
106 while ((n = read(0, buf, 80)) > 0)
107 write(1, buf, (unsigned) n);
108 }
109 exit(errno);
110 }
111