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