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 <sys/types.h> 14 #include <sys/file.h> 15 #include <signal.h> 16 17 static char MORE[] = "more"; 18 extern char *_ss_pager_name; 19 extern char *getenv(); 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(); 29 30 #ifndef NO_FORK 31 int ss_pager_create() 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 */ 59 int ss_pager_create() 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 69 void ss_page_stdin() 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