signal.c revision 191930
11556Srgrimes/* 21556Srgrimes * Copyright (C) 1984-2008 Mark Nudelman 31556Srgrimes * 41556Srgrimes * You may distribute under the terms of either the GNU General Public 51556Srgrimes * License or the Less License, as specified in the README file. 61556Srgrimes * 71556Srgrimes * For more information about less, or for information on how to 81556Srgrimes * contact the author, see the README file. 91556Srgrimes */ 101556Srgrimes 111556Srgrimes/* $FreeBSD: head/contrib/less/signal.c 191930 2009-05-09 01:35:27Z delphij $ */ 121556Srgrimes 131556Srgrimes/* 141556Srgrimes * Routines dealing with signals. 151556Srgrimes * 161556Srgrimes * A signal usually merely causes a bit to be set in the "signals" word. 171556Srgrimes * At some convenient time, the mainline code checks to see if any 181556Srgrimes * signals need processing by calling psignal(). 191556Srgrimes * If we happen to be reading from a file [in iread()] at the time 201556Srgrimes * the signal is received, we call intread to interrupt the iread. 211556Srgrimes */ 221556Srgrimes 231556Srgrimes#include "less.h" 241556Srgrimes#include <signal.h> 251556Srgrimes 261556Srgrimes/* 271556Srgrimes * "sigs" contains bits indicating signals which need to be processed. 281556Srgrimes */ 291556Srgrimespublic int sigs; 301556Srgrimes 311556Srgrimesextern int sc_width, sc_height; 3217987Speterextern int screen_trashed; 3350471Speterextern int lnloop; 341556Srgrimesextern int linenums; 351556Srgrimesextern int wscroll; 361556Srgrimesextern int reading; 371556Srgrimesextern int quit_on_intr; 381556Srgrimesextern int less_is_more; 391556Srgrimesextern long jump_sline_fraction; 4046684Skris 411556Srgrimes/* 421556Srgrimes * Interrupt signal handler. 431556Srgrimes */ 441556Srgrimes /* ARGSUSED*/ 451556Srgrimes static RETSIGTYPE 461556Srgrimesu_interrupt(type) 4738521Scracauer int type; 481556Srgrimes{ 491556Srgrimes bell(); 501556Srgrimes#if OS2 511556Srgrimes LSIGNAL(SIGINT, SIG_ACK); 521556Srgrimes#endif 531556Srgrimes LSIGNAL(SIGINT, u_interrupt); 5438530Scracauer sigs |= S_INTERRUPT; 551556Srgrimes#if MSDOS_COMPILER==DJGPPC 561556Srgrimes /* 571556Srgrimes * If a keyboard has been hit, it must be Ctrl-C 581556Srgrimes * (as opposed to Ctrl-Break), so consume it. 59218306Sjilles * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 601556Srgrimes */ 611556Srgrimes if (kbhit()) 621556Srgrimes getkey(); 631556Srgrimes#endif 641556Srgrimes if (less_is_more) 651556Srgrimes quit(0); 661556Srgrimes if (reading) 671556Srgrimes intread(); /* May longjmp */ 681556Srgrimes} 6938521Scracauer 7038521Scracauer#ifdef SIGTSTP 711556Srgrimes/* 721556Srgrimes * "Stop" (^Z) signal handler. 7317987Speter */ 74199660Sjilles /* ARGSUSED*/ 75199660Sjilles static RETSIGTYPE 761556Srgrimesstop(type) 771556Srgrimes int type; 781556Srgrimes{ 791556Srgrimes LSIGNAL(SIGTSTP, stop); 80200967Sjilles sigs |= S_STOP; 8190111Simp if (reading) 82216622Sjilles intread(); 83200967Sjilles} 84200967Sjilles#endif 851556Srgrimes 861556Srgrimes#ifdef SIGWINCH 871556Srgrimes/* 881556Srgrimes * "Window" change handler 891556Srgrimes */ 901556Srgrimes /* ARGSUSED*/ 911556Srgrimes public RETSIGTYPE 921556Srgrimeswinch(type) 931556Srgrimes 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 screen_trashed = 1; 252 } 253 } 254#endif 255 if (tsignals & S_INTERRUPT) 256 { 257 if (quit_on_intr) 258 quit(QUIT_OK); 259 } 260} 261