8888 loader: rename STAND to _STANDALONE
[unleashed.git] / bin / less / signal.c
blob5bf672c06bb97435df57007a0cdc310803cc97ee
1 /*
2 * Copyright (C) 1984-2012 Mark Nudelman
3 * Modified for use with illumos by Garrett D'Amore.
4 * Copyright 2015 Garrett D'Amore <garrett@damore.org>
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.
9 * For more information, see the README file.
13 * Routines dealing with signals.
15 * A signal usually merely causes a bit to be set in the "signals" word.
16 * At some convenient time, the mainline code checks to see if any
17 * signals need processing by calling psignal().
20 #include <signal.h>
22 #include "less.h"
25 * "sigs" contains bits indicating signals which need to be processed.
27 volatile sig_atomic_t sigs;
29 extern int sc_width, sc_height;
30 extern int screen_trashed;
31 extern int linenums;
32 extern int wscroll;
33 extern int quit_on_intr;
34 extern long jump_sline_fraction;
37 * Interrupt signal handler.
39 static void
40 u_interrupt(int type)
42 sigs |= S_INTERRUPT;
46 * "Stop" (^Z) signal handler.
48 static void
49 stop(int type)
51 sigs |= S_STOP;
55 * "Window" change handler
57 void
58 sigwinch(int type)
60 sigs |= S_WINCH;
64 * Set up the signal handlers.
66 void
67 init_signals(int on)
69 if (on) {
71 * Set signal handlers.
73 (void) lsignal(SIGINT, u_interrupt);
74 (void) lsignal(SIGTSTP, stop);
75 (void) lsignal(SIGWINCH, sigwinch);
76 (void) lsignal(SIGQUIT, SIG_IGN);
77 } else {
79 * Restore signals to defaults.
81 (void) lsignal(SIGINT, SIG_DFL);
82 (void) lsignal(SIGTSTP, SIG_DFL);
83 (void) lsignal(SIGWINCH, SIG_IGN);
84 (void) lsignal(SIGQUIT, SIG_DFL);
89 * Process any signals we have received.
90 * A received signal cause a bit to be set in "sigs".
92 void
93 psignals(void)
95 int tsignals;
97 if ((tsignals = sigs) == 0)
98 return;
99 sigs = 0;
101 if (tsignals & S_STOP) {
103 * Clean up the terminal.
105 lsignal(SIGTTOU, SIG_IGN);
106 clear_bot();
107 deinit();
108 flush(0);
109 raw_mode(0);
110 lsignal(SIGTTOU, SIG_DFL);
111 lsignal(SIGTSTP, SIG_DFL);
112 kill(getpid(), SIGTSTP);
114 * ... Bye bye. ...
115 * Hopefully we'll be back later and resume here...
116 * Reset the terminal and arrange to repaint the
117 * screen when we get back to the main command loop.
119 lsignal(SIGTSTP, stop);
120 raw_mode(1);
121 init();
122 screen_trashed = 1;
123 tsignals |= S_WINCH;
125 if (tsignals & S_WINCH) {
126 int old_width, old_height;
128 * Re-execute scrsize() to read the new window size.
130 old_width = sc_width;
131 old_height = sc_height;
132 get_term();
133 if (sc_width != old_width || sc_height != old_height) {
134 wscroll = (sc_height + 1) / 2;
135 calc_jump_sline();
136 calc_shift_count();
137 screen_trashed = 1;
140 if (tsignals & S_INTERRUPT) {
141 ring_bell();
142 if (quit_on_intr)
143 quit(QUIT_INTERRUPT);
148 * Custom version of signal() that causes syscalls to be interrupted.
150 void *
151 lsignal(int s, void (*a)(int))
153 struct sigaction sa, osa;
155 sa.sa_handler = a;
156 sigemptyset(&sa.sa_mask);
157 sa.sa_flags = 0; /* don't restart system calls */
158 if (sigaction(s, &sa, &osa) != 0)
159 return (SIG_ERR);
160 return (osa.sa_handler);