11133e27eSPeter Avalos /*
2*e433da38SAaron LI * Copyright (C) 1984-2024 Mark Nudelman
31133e27eSPeter Avalos *
41133e27eSPeter Avalos * You may distribute under the terms of either the GNU General Public
51133e27eSPeter Avalos * License or the Less License, as specified in the README file.
61133e27eSPeter Avalos *
7e639dc31SJohn Marino * For more information, see the README file.
81133e27eSPeter Avalos */
91133e27eSPeter Avalos
101133e27eSPeter Avalos
111133e27eSPeter Avalos /*
121133e27eSPeter Avalos * Routines dealing with signals.
131133e27eSPeter Avalos *
141133e27eSPeter Avalos * A signal usually merely causes a bit to be set in the "signals" word.
151133e27eSPeter Avalos * At some convenient time, the mainline code checks to see if any
161133e27eSPeter Avalos * signals need processing by calling psignal().
171133e27eSPeter Avalos * If we happen to be reading from a file [in iread()] at the time
181133e27eSPeter Avalos * the signal is received, we call intread to interrupt the iread.
191133e27eSPeter Avalos */
201133e27eSPeter Avalos
211133e27eSPeter Avalos #include "less.h"
221133e27eSPeter Avalos #include <signal.h>
231133e27eSPeter Avalos
241133e27eSPeter Avalos /*
251133e27eSPeter Avalos * "sigs" contains bits indicating signals which need to be processed.
261133e27eSPeter Avalos */
271133e27eSPeter Avalos public int sigs;
281133e27eSPeter Avalos
291133e27eSPeter Avalos extern int sc_width, sc_height;
301133e27eSPeter Avalos extern int linenums;
311133e27eSPeter Avalos extern int wscroll;
321133e27eSPeter Avalos extern int reading;
331133e27eSPeter Avalos extern int quit_on_intr;
341133e27eSPeter Avalos extern long jump_sline_fraction;
351133e27eSPeter Avalos
361133e27eSPeter Avalos /*
371133e27eSPeter Avalos * Interrupt signal handler.
381133e27eSPeter Avalos */
3902d62a0fSDaniel Fojt #if MSDOS_COMPILER!=WIN32C
401133e27eSPeter Avalos /* ARGSUSED*/
u_interrupt(int type)41320d7c8aSAaron LI static RETSIGTYPE u_interrupt(int type)
421133e27eSPeter Avalos {
43*e433da38SAaron LI (void) type;
448be36e5bSPeter Avalos bell();
451133e27eSPeter Avalos #if OS2
461133e27eSPeter Avalos LSIGNAL(SIGINT, SIG_ACK);
471133e27eSPeter Avalos #endif
481133e27eSPeter Avalos LSIGNAL(SIGINT, u_interrupt);
491133e27eSPeter Avalos sigs |= S_INTERRUPT;
501133e27eSPeter Avalos #if MSDOS_COMPILER==DJGPPC
511133e27eSPeter Avalos /*
521133e27eSPeter Avalos * If a keyboard has been hit, it must be Ctrl-C
531133e27eSPeter Avalos * (as opposed to Ctrl-Break), so consume it.
541133e27eSPeter Avalos * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
551133e27eSPeter Avalos */
561133e27eSPeter Avalos if (kbhit())
571133e27eSPeter Avalos getkey();
581133e27eSPeter Avalos #endif
590c7ad07eSAntonio Huete Jimenez #if HILITE_SEARCH
600c7ad07eSAntonio Huete Jimenez set_filter_pattern(NULL, 0);
610c7ad07eSAntonio Huete Jimenez #endif
621133e27eSPeter Avalos if (reading)
638be36e5bSPeter Avalos intread(); /* May longjmp */
641133e27eSPeter Avalos }
6502d62a0fSDaniel Fojt #endif
661133e27eSPeter Avalos
671133e27eSPeter Avalos #ifdef SIGTSTP
681133e27eSPeter Avalos /*
691133e27eSPeter Avalos * "Stop" (^Z) signal handler.
701133e27eSPeter Avalos */
711133e27eSPeter Avalos /* ARGSUSED*/
stop(int type)72320d7c8aSAaron LI static RETSIGTYPE stop(int type)
731133e27eSPeter Avalos {
74*e433da38SAaron LI (void) type;
751133e27eSPeter Avalos LSIGNAL(SIGTSTP, stop);
761133e27eSPeter Avalos sigs |= S_STOP;
771133e27eSPeter Avalos if (reading)
781133e27eSPeter Avalos intread();
791133e27eSPeter Avalos }
801133e27eSPeter Avalos #endif
811133e27eSPeter Avalos
8202d62a0fSDaniel Fojt #undef SIG_LESSWINDOW
831133e27eSPeter Avalos #ifdef SIGWINCH
8402d62a0fSDaniel Fojt #define SIG_LESSWINDOW SIGWINCH
851133e27eSPeter Avalos #else
861133e27eSPeter Avalos #ifdef SIGWIND
8702d62a0fSDaniel Fojt #define SIG_LESSWINDOW SIGWIND
8802d62a0fSDaniel Fojt #endif
8902d62a0fSDaniel Fojt #endif
9002d62a0fSDaniel Fojt
9102d62a0fSDaniel Fojt #ifdef SIG_LESSWINDOW
921133e27eSPeter Avalos /*
931133e27eSPeter Avalos * "Window" change handler
941133e27eSPeter Avalos */
951133e27eSPeter Avalos /* ARGSUSED*/
winch(int type)96320d7c8aSAaron LI public RETSIGTYPE winch(int type)
971133e27eSPeter Avalos {
98*e433da38SAaron LI (void) type;
9902d62a0fSDaniel Fojt LSIGNAL(SIG_LESSWINDOW, winch);
1001133e27eSPeter Avalos sigs |= S_WINCH;
1011133e27eSPeter Avalos if (reading)
1021133e27eSPeter Avalos intread();
1031133e27eSPeter Avalos }
1041133e27eSPeter Avalos #endif
1051133e27eSPeter Avalos
1061133e27eSPeter Avalos #if MSDOS_COMPILER==WIN32C
1071133e27eSPeter Avalos /*
1081133e27eSPeter Avalos * Handle CTRL-C and CTRL-BREAK keys.
1091133e27eSPeter Avalos */
11002d62a0fSDaniel Fojt #define WIN32_LEAN_AND_MEAN
11102d62a0fSDaniel Fojt #include <windows.h>
1121133e27eSPeter Avalos
wbreak_handler(DWORD dwCtrlType)113320d7c8aSAaron LI static BOOL WINAPI wbreak_handler(DWORD dwCtrlType)
1141133e27eSPeter Avalos {
1151133e27eSPeter Avalos switch (dwCtrlType)
1161133e27eSPeter Avalos {
1171133e27eSPeter Avalos case CTRL_C_EVENT:
1181133e27eSPeter Avalos case CTRL_BREAK_EVENT:
1191133e27eSPeter Avalos sigs |= S_INTERRUPT;
1200c7ad07eSAntonio Huete Jimenez #if HILITE_SEARCH
1210c7ad07eSAntonio Huete Jimenez set_filter_pattern(NULL, 0);
1220c7ad07eSAntonio Huete Jimenez #endif
1231133e27eSPeter Avalos return (TRUE);
1241133e27eSPeter Avalos default:
1251133e27eSPeter Avalos break;
1261133e27eSPeter Avalos }
1271133e27eSPeter Avalos return (FALSE);
1281133e27eSPeter Avalos }
1291133e27eSPeter Avalos #endif
1301133e27eSPeter Avalos
terminate(int type)131320d7c8aSAaron LI static RETSIGTYPE terminate(int type)
13202d62a0fSDaniel Fojt {
133*e433da38SAaron LI (void) type;
13402d62a0fSDaniel Fojt quit(15);
13502d62a0fSDaniel Fojt }
13602d62a0fSDaniel Fojt
1371133e27eSPeter Avalos /*
1381133e27eSPeter Avalos * Set up the signal handlers.
1391133e27eSPeter Avalos */
init_signals(int on)140320d7c8aSAaron LI public void init_signals(int on)
1411133e27eSPeter Avalos {
1421133e27eSPeter Avalos if (on)
1431133e27eSPeter Avalos {
1441133e27eSPeter Avalos /*
1451133e27eSPeter Avalos * Set signal handlers.
1461133e27eSPeter Avalos */
1471133e27eSPeter Avalos #if MSDOS_COMPILER==WIN32C
1481133e27eSPeter Avalos SetConsoleCtrlHandler(wbreak_handler, TRUE);
14902d62a0fSDaniel Fojt #else
15002d62a0fSDaniel Fojt (void) LSIGNAL(SIGINT, u_interrupt);
1511133e27eSPeter Avalos #endif
1521133e27eSPeter Avalos #ifdef SIGTSTP
153*e433da38SAaron LI (void) LSIGNAL(SIGTSTP, !secure_allow(SF_STOP) ? SIG_IGN : stop);
1541133e27eSPeter Avalos #endif
1551133e27eSPeter Avalos #ifdef SIGWINCH
1561133e27eSPeter Avalos (void) LSIGNAL(SIGWINCH, winch);
1571133e27eSPeter Avalos #endif
1581133e27eSPeter Avalos #ifdef SIGWIND
1591133e27eSPeter Avalos (void) LSIGNAL(SIGWIND, winch);
1601133e27eSPeter Avalos #endif
1611133e27eSPeter Avalos #ifdef SIGQUIT
1621133e27eSPeter Avalos (void) LSIGNAL(SIGQUIT, SIG_IGN);
1631133e27eSPeter Avalos #endif
16402d62a0fSDaniel Fojt #ifdef SIGTERM
16502d62a0fSDaniel Fojt (void) LSIGNAL(SIGTERM, terminate);
16602d62a0fSDaniel Fojt #endif
1671133e27eSPeter Avalos } else
1681133e27eSPeter Avalos {
1691133e27eSPeter Avalos /*
1701133e27eSPeter Avalos * Restore signals to defaults.
1711133e27eSPeter Avalos */
1721133e27eSPeter Avalos #if MSDOS_COMPILER==WIN32C
1731133e27eSPeter Avalos SetConsoleCtrlHandler(wbreak_handler, FALSE);
17402d62a0fSDaniel Fojt #else
17502d62a0fSDaniel Fojt (void) LSIGNAL(SIGINT, SIG_DFL);
1761133e27eSPeter Avalos #endif
1771133e27eSPeter Avalos #ifdef SIGTSTP
1781133e27eSPeter Avalos (void) LSIGNAL(SIGTSTP, SIG_DFL);
1791133e27eSPeter Avalos #endif
1801133e27eSPeter Avalos #ifdef SIGWINCH
1811133e27eSPeter Avalos (void) LSIGNAL(SIGWINCH, SIG_IGN);
1821133e27eSPeter Avalos #endif
1831133e27eSPeter Avalos #ifdef SIGWIND
1841133e27eSPeter Avalos (void) LSIGNAL(SIGWIND, SIG_IGN);
1851133e27eSPeter Avalos #endif
1861133e27eSPeter Avalos #ifdef SIGQUIT
1871133e27eSPeter Avalos (void) LSIGNAL(SIGQUIT, SIG_DFL);
1881133e27eSPeter Avalos #endif
18902d62a0fSDaniel Fojt #ifdef SIGTERM
19002d62a0fSDaniel Fojt (void) LSIGNAL(SIGTERM, SIG_DFL);
19102d62a0fSDaniel Fojt #endif
1921133e27eSPeter Avalos }
1931133e27eSPeter Avalos }
1941133e27eSPeter Avalos
1951133e27eSPeter Avalos /*
1961133e27eSPeter Avalos * Process any signals we have received.
1971133e27eSPeter Avalos * A received signal cause a bit to be set in "sigs".
1981133e27eSPeter Avalos */
psignals(void)199320d7c8aSAaron LI public void psignals(void)
2001133e27eSPeter Avalos {
20102d62a0fSDaniel Fojt int tsignals;
2021133e27eSPeter Avalos
2031133e27eSPeter Avalos if ((tsignals = sigs) == 0)
2041133e27eSPeter Avalos return;
2051133e27eSPeter Avalos sigs = 0;
2061133e27eSPeter Avalos
2071133e27eSPeter Avalos #ifdef SIGTSTP
2081133e27eSPeter Avalos if (tsignals & S_STOP)
2091133e27eSPeter Avalos {
2101133e27eSPeter Avalos /*
2111133e27eSPeter Avalos * Clean up the terminal.
2121133e27eSPeter Avalos */
2131133e27eSPeter Avalos #ifdef SIGTTOU
2141133e27eSPeter Avalos LSIGNAL(SIGTTOU, SIG_IGN);
2151133e27eSPeter Avalos #endif
2161133e27eSPeter Avalos clear_bot();
2171133e27eSPeter Avalos deinit();
2181133e27eSPeter Avalos flush();
2191133e27eSPeter Avalos raw_mode(0);
2201133e27eSPeter Avalos #ifdef SIGTTOU
2211133e27eSPeter Avalos LSIGNAL(SIGTTOU, SIG_DFL);
2221133e27eSPeter Avalos #endif
2231133e27eSPeter Avalos LSIGNAL(SIGTSTP, SIG_DFL);
2241133e27eSPeter Avalos kill(getpid(), SIGTSTP);
2251133e27eSPeter Avalos /*
2261133e27eSPeter Avalos * ... Bye bye. ...
2271133e27eSPeter Avalos * Hopefully we'll be back later and resume here...
2281133e27eSPeter Avalos * Reset the terminal and arrange to repaint the
2291133e27eSPeter Avalos * screen when we get back to the main command loop.
2301133e27eSPeter Avalos */
2311133e27eSPeter Avalos LSIGNAL(SIGTSTP, stop);
2321133e27eSPeter Avalos raw_mode(1);
2331133e27eSPeter Avalos init();
234*e433da38SAaron LI screen_trashed();
2351133e27eSPeter Avalos tsignals |= S_WINCH;
2361133e27eSPeter Avalos }
2371133e27eSPeter Avalos #endif
2381133e27eSPeter Avalos #ifdef S_WINCH
2391133e27eSPeter Avalos if (tsignals & S_WINCH)
2401133e27eSPeter Avalos {
2411133e27eSPeter Avalos int old_width, old_height;
2421133e27eSPeter Avalos /*
2431133e27eSPeter Avalos * Re-execute scrsize() to read the new window size.
2441133e27eSPeter Avalos */
2451133e27eSPeter Avalos old_width = sc_width;
2461133e27eSPeter Avalos old_height = sc_height;
2471133e27eSPeter Avalos get_term();
2481133e27eSPeter Avalos if (sc_width != old_width || sc_height != old_height)
2491133e27eSPeter Avalos {
2501133e27eSPeter Avalos wscroll = (sc_height + 1) / 2;
2511133e27eSPeter Avalos calc_jump_sline();
252a9adbba3SJan Lentfer calc_shift_count();
253*e433da38SAaron LI calc_match_shift();
2541133e27eSPeter Avalos }
255*e433da38SAaron LI screen_trashed();
2561133e27eSPeter Avalos }
2571133e27eSPeter Avalos #endif
2581133e27eSPeter Avalos if (tsignals & S_INTERRUPT)
2591133e27eSPeter Avalos {
2601133e27eSPeter Avalos if (quit_on_intr)
26125ce721eSPeter Avalos quit(QUIT_INTERRUPT);
262*e433da38SAaron LI getcc_clear();
263*e433da38SAaron LI #if MSDOS_COMPILER==WIN32C
264*e433da38SAaron LI win32_getch_clear();
265*e433da38SAaron LI #endif
2661133e27eSPeter Avalos }
2671133e27eSPeter Avalos }
268