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