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