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