1 /* $NetBSD: signal.c,v 1.6 2004/09/01 01:46:56 chs Exp $ */ 2 3 /* 4 * Copyright (c) 1988 Mark Nudelman 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 #ifndef lint 35 #if 0 36 static char sccsid[] = "@(#)signal.c 8.1 (Berkeley) 6/6/93"; 37 #else 38 __RCSID("$NetBSD: signal.c,v 1.6 2004/09/01 01:46:56 chs Exp $"); 39 #endif 40 #endif /* not lint */ 41 42 /* 43 * Routines dealing with signals. 44 * 45 * A signal usually merely causes a bit to be set in the "signals" word. 46 * At some convenient time, the mainline code checks to see if any 47 * signals need processing by calling psignal(). 48 * If we happen to be reading from a file [in iread()] at the time 49 * the signal is received, we call intread to interrupt the iread. 50 */ 51 52 #include <signal.h> 53 #include <unistd.h> 54 55 #include "less.h" 56 #include "extern.h" 57 58 /* 59 * "sigs" contains bits indicating signals which need to be processed. 60 */ 61 int sigs; 62 63 #ifdef SIGTSTP 64 #define S_STOP 02 65 #endif 66 #if defined(SIGWINCH) || defined(SIGWIND) 67 #define S_WINCH 04 68 #endif 69 70 71 static void purgeandquit __P((int)); 72 73 #ifdef SIGTSTP 74 static void stop __P((int)); 75 /* 76 * "Stop" (^Z) signal handler. 77 */ 78 static void 79 stop(n) 80 int n; 81 { 82 (void)signal(SIGTSTP, stop); 83 sigs |= S_STOP; 84 if (reading) 85 intread(); 86 } 87 #endif 88 89 #ifdef SIGWINCH 90 /* 91 * "Window" change handler 92 */ 93 void 94 winch(n) 95 int n; 96 { 97 (void)signal(SIGWINCH, winch); 98 sigs |= S_WINCH; 99 if (reading) 100 intread(); 101 } 102 #else 103 #ifdef SIGWIND 104 /* 105 * "Window" change handler 106 */ 107 winch() 108 { 109 (void)signal(SIGWIND, winch); 110 sigs |= S_WINCH; 111 if (reading) 112 intread(); 113 } 114 #endif 115 #endif 116 117 static void 118 purgeandquit(n) 119 int n; 120 { 121 122 purge(); /* purge buffered output */ 123 quit(); 124 } 125 126 /* 127 * Set up the signal handlers. 128 */ 129 void 130 init_signals(on) 131 int on; 132 { 133 if (on) 134 { 135 /* 136 * Set signal handlers. 137 */ 138 (void)signal(SIGINT, purgeandquit); 139 #ifdef SIGTSTP 140 (void)signal(SIGTSTP, stop); 141 #endif 142 #ifdef SIGWINCH 143 (void)signal(SIGWINCH, winch); 144 #else 145 #ifdef SIGWIND 146 (void)signal(SIGWIND, winch); 147 #endif 148 #endif 149 } else 150 { 151 /* 152 * Restore signals to defaults. 153 */ 154 (void)signal(SIGINT, SIG_DFL); 155 #ifdef SIGTSTP 156 (void)signal(SIGTSTP, SIG_DFL); 157 #endif 158 #ifdef SIGWINCH 159 (void)signal(SIGWINCH, SIG_IGN); 160 #endif 161 #ifdef SIGWIND 162 (void)signal(SIGWIND, SIG_IGN); 163 #endif 164 } 165 } 166 167 /* 168 * Process any signals we have received. 169 * A received signal cause a bit to be set in "sigs". 170 */ 171 void 172 psignals() 173 { 174 int tsignals; 175 176 if ((tsignals = sigs) == 0) 177 return; 178 sigs = 0; 179 180 #ifdef S_WINCH 181 if (tsignals & S_WINCH) 182 { 183 int old_width, old_height; 184 /* 185 * Re-execute get_term() to read the new window size. 186 */ 187 old_width = sc_width; 188 old_height = sc_height; 189 get_term(); 190 if (sc_width != old_width || sc_height != old_height) 191 { 192 scroll_lines = (sc_height + 1) / 2; 193 screen_trashed = 1; 194 } 195 } 196 #endif 197 #ifdef SIGTSTP 198 if (tsignals & S_STOP) 199 { 200 /* 201 * Clean up the terminal. 202 */ 203 #ifdef SIGTTOU 204 (void)signal(SIGTTOU, SIG_IGN); 205 #endif 206 lower_left(); 207 clear_eol(); 208 deinit(); 209 (void)flush(); 210 raw_mode(0); 211 #ifdef SIGTTOU 212 (void)signal(SIGTTOU, SIG_DFL); 213 #endif 214 (void)signal(SIGTSTP, SIG_DFL); 215 (void)kill(getpid(), SIGTSTP); 216 /* 217 * ... Bye bye. ... 218 * Hopefully we'll be back later and resume here... 219 * Reset the terminal and arrange to repaint the 220 * screen when we get back to the main command loop. 221 */ 222 (void)signal(SIGTSTP, stop); 223 raw_mode(1); 224 init(); 225 screen_trashed = 1; 226 } 227 #endif 228 } 229