signal.c revision 161478
120253Sjoerg/* 220302Sjoerg * Copyright (C) 1984-2004 Mark Nudelman 320302Sjoerg * 420253Sjoerg * You may distribute under the terms of either the GNU General Public 520253Sjoerg * License or the Less License, as specified in the README file. 620253Sjoerg * 720253Sjoerg * For more information about less, or for information on how to 820253Sjoerg * contact the author, see the README file. 920302Sjoerg */ 1020253Sjoerg 1120253Sjoerg/* $FreeBSD: head/contrib/less/signal.c 161478 2006-08-20 15:50:51Z delphij $ */ 1220253Sjoerg 1320253Sjoerg/* 1420302Sjoerg * Routines dealing with signals. 1520253Sjoerg * 1620253Sjoerg * A signal usually merely causes a bit to be set in the "signals" word. 1720302Sjoerg * At some convenient time, the mainline code checks to see if any 1820253Sjoerg * signals need processing by calling psignal(). 1920253Sjoerg * If we happen to be reading from a file [in iread()] at the time 2020253Sjoerg * the signal is received, we call intread to interrupt the iread. 2120253Sjoerg */ 2220253Sjoerg 2320253Sjoerg#include "less.h" 2420253Sjoerg#include <signal.h> 2544229Sdavidn 2620253Sjoerg/* 2720253Sjoerg * "sigs" contains bits indicating signals which need to be processed. 2830259Scharnier */ 2930259Scharnierpublic int sigs; 3050479Speter 3130259Scharnierextern int sc_width, sc_height; 3230259Scharnierextern int screen_trashed; 3330259Scharnierextern int lnloop; 3430259Scharnierextern int linenums; 3520253Sjoergextern int wscroll; 3620253Sjoergextern int reading; 3720253Sjoergextern int quit_on_intr; 3830259Scharnierextern int more_mode; 3920253Sjoerg 4020555Sdavidn/* 4120555Sdavidn * Interrupt signal handler. 4220555Sdavidn */ 4330259Scharnier /* ARGSUSED*/ 4422394Sdavidn static RETSIGTYPE 4564918Sgreenu_interrupt(type) 4622394Sdavidn int type; 4720555Sdavidn{ 4822394Sdavidn#if OS2 4920253Sjoerg LSIGNAL(SIGINT, SIG_ACK); 5020253Sjoerg#endif 5120253Sjoerg LSIGNAL(SIGINT, u_interrupt); 5223318Sache sigs |= S_INTERRUPT; 5322394Sdavidn#if MSDOS_COMPILER==DJGPPC 5422394Sdavidn /* 5523318Sache * If a keyboard has been hit, it must be Ctrl-C 5622394Sdavidn * (as opposed to Ctrl-Break), so consume it. 5722394Sdavidn * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 5852512Sdavidn */ 5924214Sache if (kbhit()) 6044386Sdavidn getkey(); 6120253Sjoerg#endif 6220253Sjoerg if (more_mode) 6320253Sjoerg quit(0); 6420253Sjoerg if (reading) 6520253Sjoerg intread(); 6620253Sjoerg} 6720253Sjoerg 6820253Sjoerg#ifdef SIGTSTP 6920253Sjoerg/* 7085145Sache * "Stop" (^Z) signal handler. 7120253Sjoerg */ 7220253Sjoerg /* ARGSUSED*/ 7320253Sjoerg static RETSIGTYPE 7420253Sjoergstop(type) 7520253Sjoerg int type; 7620253Sjoerg{ 7720253Sjoerg LSIGNAL(SIGTSTP, stop); 7820253Sjoerg sigs |= S_STOP; 7920253Sjoerg if (reading) 8020253Sjoerg intread(); 8120253Sjoerg} 8220253Sjoerg#endif 8320253Sjoerg 8420253Sjoerg#ifdef SIGWINCH 8520253Sjoerg/* 8620253Sjoerg * "Window" change handler 8720253Sjoerg */ 8820253Sjoerg /* ARGSUSED*/ 89124382Siedowse public RETSIGTYPE 9020253Sjoergwinch(type) 9120253Sjoerg int type; 9220253Sjoerg{ 9320253Sjoerg LSIGNAL(SIGWINCH, winch); 9420253Sjoerg sigs |= S_WINCH; 9520253Sjoerg if (reading) 9620253Sjoerg intread(); 9720253Sjoerg} 9820253Sjoerg#else 9920253Sjoerg#ifdef SIGWIND 10020253Sjoerg/* 10120253Sjoerg * "Window" change handler 10220253Sjoerg */ 10320253Sjoerg /* ARGSUSED*/ 10420253Sjoerg public RETSIGTYPE 10520253Sjoergwinch(type) 10620253Sjoerg int type; 10752527Sdavidn{ 10820253Sjoerg LSIGNAL(SIGWIND, winch); 10952512Sdavidn sigs |= S_WINCH; 11020253Sjoerg if (reading) 11120253Sjoerg intread(); 11220253Sjoerg} 11320253Sjoerg#endif 11420253Sjoerg#endif 11520253Sjoerg 11620747Sdavidn#if MSDOS_COMPILER==WIN32C 11782868Sdd/* 11820253Sjoerg * Handle CTRL-C and CTRL-BREAK keys. 11920253Sjoerg */ 12020253Sjoerg#include "windows.h" 12120253Sjoerg 12220253Sjoerg static BOOL WINAPI 12320253Sjoergwbreak_handler(dwCtrlType) 12420253Sjoerg DWORD dwCtrlType; 12520253Sjoerg{ 12620253Sjoerg switch (dwCtrlType) 12720253Sjoerg { 12856000Sdavidn case CTRL_C_EVENT: 12920253Sjoerg case CTRL_BREAK_EVENT: 13020253Sjoerg sigs |= S_INTERRUPT; 13156000Sdavidn return (TRUE); 13256000Sdavidn default: 13356000Sdavidn break; 13420253Sjoerg } 13520253Sjoerg return (FALSE); 13652512Sdavidn} 13720253Sjoerg#endif 13820267Sjoerg 13920267Sjoerg/* 14020267Sjoerg * Set up the signal handlers. 14120267Sjoerg */ 14220267Sjoerg public void 14320267Sjoerginit_signals(on) 14420267Sjoerg int on; 14520267Sjoerg{ 14620267Sjoerg if (on) 14720267Sjoerg { 14820267Sjoerg /* 14920267Sjoerg * Set signal handlers. 15020267Sjoerg */ 15120267Sjoerg (void) LSIGNAL(SIGINT, u_interrupt); 15220253Sjoerg#if MSDOS_COMPILER==WIN32C 15320253Sjoerg SetConsoleCtrlHandler(wbreak_handler, TRUE); 15420253Sjoerg#endif 15520253Sjoerg#ifdef SIGTSTP 15620267Sjoerg (void) LSIGNAL(SIGTSTP, stop); 15720253Sjoerg#endif 15821052Sdavidn#ifdef SIGWINCH 15921052Sdavidn (void) LSIGNAL(SIGWINCH, winch); 16021052Sdavidn#else 16121052Sdavidn#ifdef SIGWIND 16221052Sdavidn (void) LSIGNAL(SIGWIND, winch); 16321052Sdavidn#endif 16421052Sdavidn#ifdef SIGQUIT 16521052Sdavidn (void) LSIGNAL(SIGQUIT, SIG_IGN); 16621052Sdavidn#endif 16721052Sdavidn#endif 16821052Sdavidn } else 16921052Sdavidn { 17030259Scharnier /* 17121052Sdavidn * Restore signals to defaults. 17221052Sdavidn */ 17321052Sdavidn (void) LSIGNAL(SIGINT, SIG_DFL); 17421052Sdavidn#if MSDOS_COMPILER==WIN32C 17521242Sdavidn SetConsoleCtrlHandler(wbreak_handler, FALSE); 17621242Sdavidn#endif 17721242Sdavidn#ifdef SIGTSTP 17821242Sdavidn (void) LSIGNAL(SIGTSTP, SIG_DFL); 17921242Sdavidn#endif 18021242Sdavidn#ifdef SIGWINCH 18121242Sdavidn (void) LSIGNAL(SIGWINCH, SIG_IGN); 18221242Sdavidn#endif 18321242Sdavidn#ifdef SIGWIND 18421242Sdavidn (void) LSIGNAL(SIGWIND, SIG_IGN); 18521242Sdavidn#endif 18621242Sdavidn#ifdef SIGQUIT 18721242Sdavidn (void) LSIGNAL(SIGQUIT, SIG_DFL); 18821242Sdavidn#endif 18921242Sdavidn } 19021052Sdavidn} 19121052Sdavidn 19221242Sdavidn/* 19321242Sdavidn * Process any signals we have received. 19421242Sdavidn * A received signal cause a bit to be set in "sigs". 19521242Sdavidn */ 19621242Sdavidn public void 19721242Sdavidnpsignals() 19821242Sdavidn{ 19921242Sdavidn register int tsignals; 20030259Scharnier 20121242Sdavidn if ((tsignals = sigs) == 0) 20221242Sdavidn return; 20321052Sdavidn sigs = 0; 20421242Sdavidn 20521052Sdavidn#ifdef SIGTSTP 20630259Scharnier if (tsignals & S_STOP) 20721052Sdavidn { 20821052Sdavidn /* 20921052Sdavidn * Clean up the terminal. 21021052Sdavidn */ 21130259Scharnier#ifdef SIGTTOU 21221052Sdavidn LSIGNAL(SIGTTOU, SIG_IGN); 21321052Sdavidn#endif 21420253Sjoerg clear_bot(); 21520253Sjoerg deinit(); 21620253Sjoerg flush(); 21721330Sdavidn raw_mode(0); 21821330Sdavidn#ifdef SIGTTOU 21921330Sdavidn LSIGNAL(SIGTTOU, SIG_DFL); 22020253Sjoerg#endif 22120253Sjoerg LSIGNAL(SIGTSTP, SIG_DFL); 22220253Sjoerg kill(getpid(), SIGTSTP); 22320253Sjoerg /* 22463596Sdavidn * ... Bye bye. ... 22563596Sdavidn * Hopefully we'll be back later and resume here... 22663596Sdavidn * Reset the terminal and arrange to repaint the 22763596Sdavidn * screen when we get back to the main command loop. 22863596Sdavidn */ 22963596Sdavidn LSIGNAL(SIGTSTP, stop); 23063596Sdavidn raw_mode(1); 23163596Sdavidn init(); 23220253Sjoerg screen_trashed = 1; 23320253Sjoerg tsignals |= S_WINCH; 23420253Sjoerg } 23520679Sdavidn#endif 23620253Sjoerg#ifdef S_WINCH 23720253Sjoerg if (tsignals & S_WINCH) 23852527Sdavidn { 23920253Sjoerg int old_width, old_height; 24020747Sdavidn /* 24144229Sdavidn * Re-execute scrsize() to read the new window size. 24261957Sache */ 24330259Scharnier old_width = sc_width; 24420253Sjoerg old_height = sc_height; 24520747Sdavidn get_term(); 24620747Sdavidn if (sc_width != old_width || sc_height != old_height) 24720253Sjoerg { 24820747Sdavidn wscroll = (sc_height + 1) / 2; 24920253Sjoerg screen_trashed = 1; 25020253Sjoerg } 25152527Sdavidn } 25220253Sjoerg#endif 25326088Sdavidn if (tsignals & S_INTERRUPT) 25430259Scharnier { 25520253Sjoerg if (quit_on_intr) 25652527Sdavidn quit(QUIT_OK); 25720253Sjoerg bell(); 25820253Sjoerg /* 25920253Sjoerg * {{ You may wish to replace the bell() with 26063600Sdavidn * error("Interrupt", NULL_PARG); }} 26163600Sdavidn */ 26220253Sjoerg 26320253Sjoerg /* 26430259Scharnier * If we were interrupted while in the "calculating 26520253Sjoerg * line numbers" loop, turn off line numbers. 26620253Sjoerg */ 26720253Sjoerg if (lnloop) 26820253Sjoerg { 26920253Sjoerg lnloop = 0; 27020253Sjoerg if (linenums == 2) 27120253Sjoerg screen_trashed = 1; 27220253Sjoerg linenums = 0; 27320253Sjoerg error("Line numbers turned off", NULL_PARG); 27420253Sjoerg } 27520253Sjoerg 27620253Sjoerg } 27720253Sjoerg} 27820253Sjoerg