1 /* $NetBSD: signal.c,v 1.4 2013/09/04 19:44:21 tron Exp $ */ 2 3 /* 4 * Copyright (C) 1984-2012 Mark Nudelman 5 * 6 * You may distribute under the terms of either the GNU General Public 7 * License or the Less License, as specified in the README file. 8 * 9 * For more information, see the README file. 10 */ 11 12 13 /* 14 * Routines dealing with signals. 15 * 16 * A signal usually merely causes a bit to be set in the "signals" word. 17 * At some convenient time, the mainline code checks to see if any 18 * signals need processing by calling psignal(). 19 * If we happen to be reading from a file [in iread()] at the time 20 * the signal is received, we call intread to interrupt the iread. 21 */ 22 23 #include "less.h" 24 #include <signal.h> 25 26 /* 27 * "sigs" contains bits indicating signals which need to be processed. 28 */ 29 public int sigs; 30 31 static RETSIGTYPE u_interrupt __P((int)); 32 static RETSIGTYPE stop __P((int)); 33 #if MSDOS_COMPILER==WIN32C 34 static BOOL WINAPI wbreak_handler __P((DWORD)); 35 #endif 36 37 extern int sc_width, sc_height; 38 extern int screen_trashed; 39 extern int lnloop; 40 extern int linenums; 41 extern int wscroll; 42 extern int reading; 43 extern int quit_on_intr; 44 extern long jump_sline_fraction; 45 46 /* 47 * Interrupt signal handler. 48 */ 49 /* ARGSUSED*/ 50 static RETSIGTYPE 51 u_interrupt(type) 52 int type; 53 { 54 bell(); 55 #if OS2 56 LSIGNAL(SIGINT, SIG_ACK); 57 #endif 58 LSIGNAL(SIGINT, u_interrupt); 59 sigs |= S_INTERRUPT; 60 #if MSDOS_COMPILER==DJGPPC 61 /* 62 * If a keyboard has been hit, it must be Ctrl-C 63 * (as opposed to Ctrl-Break), so consume it. 64 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 65 */ 66 if (kbhit()) 67 getkey(); 68 #endif 69 if (reading) 70 intread(); /* May longjmp */ 71 } 72 73 #ifdef SIGTSTP 74 /* 75 * "Stop" (^Z) signal handler. 76 */ 77 /* ARGSUSED*/ 78 static RETSIGTYPE 79 stop(type) 80 int type; 81 { 82 LSIGNAL(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 /* ARGSUSED*/ 94 public RETSIGTYPE 95 winch(type) 96 int type; 97 { 98 LSIGNAL(SIGWINCH, winch); 99 sigs |= S_WINCH; 100 if (reading) 101 intread(); 102 } 103 #else 104 #ifdef SIGWIND 105 /* 106 * "Window" change handler 107 */ 108 /* ARGSUSED*/ 109 public RETSIGTYPE 110 winch(type) 111 int type; 112 { 113 LSIGNAL(SIGWIND, winch); 114 sigs |= S_WINCH; 115 if (reading) 116 intread(); 117 } 118 #endif 119 #endif 120 121 #if MSDOS_COMPILER==WIN32C 122 /* 123 * Handle CTRL-C and CTRL-BREAK keys. 124 */ 125 #include "windows.h" 126 127 static BOOL WINAPI 128 wbreak_handler(dwCtrlType) 129 DWORD dwCtrlType; 130 { 131 switch (dwCtrlType) 132 { 133 case CTRL_C_EVENT: 134 case CTRL_BREAK_EVENT: 135 sigs |= S_INTERRUPT; 136 return (TRUE); 137 default: 138 break; 139 } 140 return (FALSE); 141 } 142 #endif 143 144 /* 145 * Set up the signal handlers. 146 */ 147 public void 148 init_signals(on) 149 int on; 150 { 151 if (on) 152 { 153 /* 154 * Set signal handlers. 155 */ 156 (void) LSIGNAL(SIGINT, u_interrupt); 157 #if MSDOS_COMPILER==WIN32C 158 SetConsoleCtrlHandler(wbreak_handler, TRUE); 159 #endif 160 #ifdef SIGTSTP 161 (void) LSIGNAL(SIGTSTP, stop); 162 #endif 163 #ifdef SIGWINCH 164 (void) LSIGNAL(SIGWINCH, winch); 165 #endif 166 #ifdef SIGWIND 167 (void) LSIGNAL(SIGWIND, winch); 168 #endif 169 #ifdef SIGQUIT 170 (void) LSIGNAL(SIGQUIT, SIG_IGN); 171 #endif 172 } else 173 { 174 /* 175 * Restore signals to defaults. 176 */ 177 (void) LSIGNAL(SIGINT, SIG_DFL); 178 #if MSDOS_COMPILER==WIN32C 179 SetConsoleCtrlHandler(wbreak_handler, FALSE); 180 #endif 181 #ifdef SIGTSTP 182 (void) LSIGNAL(SIGTSTP, SIG_DFL); 183 #endif 184 #ifdef SIGWINCH 185 (void) LSIGNAL(SIGWINCH, SIG_IGN); 186 #endif 187 #ifdef SIGWIND 188 (void) LSIGNAL(SIGWIND, SIG_IGN); 189 #endif 190 #ifdef SIGQUIT 191 (void) LSIGNAL(SIGQUIT, SIG_DFL); 192 #endif 193 } 194 } 195 196 /* 197 * Process any signals we have received. 198 * A received signal cause a bit to be set in "sigs". 199 */ 200 public void 201 psignals() 202 { 203 register int tsignals; 204 205 if ((tsignals = sigs) == 0) 206 return; 207 sigs = 0; 208 209 #ifdef SIGTSTP 210 if (tsignals & S_STOP) 211 { 212 /* 213 * Clean up the terminal. 214 */ 215 #ifdef SIGTTOU 216 LSIGNAL(SIGTTOU, SIG_IGN); 217 #endif 218 clear_bot(); 219 deinit(); 220 flush(); 221 raw_mode(0); 222 #ifdef SIGTTOU 223 LSIGNAL(SIGTTOU, SIG_DFL); 224 #endif 225 LSIGNAL(SIGTSTP, SIG_DFL); 226 kill(getpid(), SIGTSTP); 227 /* 228 * ... Bye bye. ... 229 * Hopefully we'll be back later and resume here... 230 * Reset the terminal and arrange to repaint the 231 * screen when we get back to the main command loop. 232 */ 233 LSIGNAL(SIGTSTP, stop); 234 raw_mode(1); 235 init(); 236 screen_trashed = 1; 237 tsignals |= S_WINCH; 238 } 239 #endif 240 #ifdef S_WINCH 241 if (tsignals & S_WINCH) 242 { 243 int old_width, old_height; 244 /* 245 * Re-execute scrsize() to read the new window size. 246 */ 247 old_width = sc_width; 248 old_height = sc_height; 249 get_term(); 250 if (sc_width != old_width || sc_height != old_height) 251 { 252 wscroll = (sc_height + 1) / 2; 253 calc_jump_sline(); 254 calc_shift_count(); 255 screen_trashed = 1; 256 } 257 } 258 #endif 259 if (tsignals & S_INTERRUPT) 260 { 261 if (quit_on_intr) 262 quit(QUIT_INTERRUPT); 263 } 264 } 265