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
23static char MORE[] = "more";
24extern char *_ss_pager_name;
25extern 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
36int 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 */
63int ss_pager_create(void)
64{
65    int fd;
66    fd = open("/dev/tty", O_WRONLY, 0);
67    return fd;
68}
69#endif
70
71void 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