xref: /freebsd/crypto/krb5/src/util/ss/pager.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
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