GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/less/less/../signal.c Lines: 24 54 44.4 %
Date: 2017-11-07 Branches: 7 18 38.9 %

Line Branch Exec Source
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>
5
 *
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.
8
 *
9
 * For more information, see the README file.
10
 */
11
12
/*
13
 * Routines dealing with signals.
14
 *
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().
18
 */
19
20
#include <signal.h>
21
22
#include "less.h"
23
24
/*
25
 * "sigs" contains bits indicating signals which need to be processed.
26
 */
27
volatile sig_atomic_t sigs;
28
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;
35
36
/*
37
 * Interrupt signal handler.
38
 */
39
static void
40
u_interrupt(int type)
41
{
42
2
	sigs |= S_INTERRUPT;
43
1
}
44
45
/*
46
 * "Stop" (^Z) signal handler.
47
 */
48
static void
49
stop(int type)
50
{
51
	sigs |= S_STOP;
52
}
53
54
/*
55
 * "Window" change handler
56
 */
57
void
58
sigwinch(int type)
59
{
60
	sigs |= S_WINCH;
61
}
62
63
/*
64
 * Set up the signal handlers.
65
 */
66
void
67
init_signals(int on)
68
{
69
78
	if (on) {
70
		/*
71
		 * Set signal handlers.
72
		 */
73
39
		(void) lsignal(SIGINT, u_interrupt);
74
39
		(void) lsignal(SIGTSTP, stop);
75
39
		(void) lsignal(SIGWINCH, sigwinch);
76
39
		(void) lsignal(SIGQUIT, SIG_IGN);
77
39
	} else {
78
		/*
79
		 * Restore signals to defaults.
80
		 */
81
		(void) lsignal(SIGINT, SIG_DFL);
82
		(void) lsignal(SIGTSTP, SIG_DFL);
83
		(void) lsignal(SIGWINCH, SIG_IGN);
84
		(void) lsignal(SIGQUIT, SIG_DFL);
85
	}
86
39
}
87
88
/*
89
 * Process any signals we have received.
90
 * A received signal cause a bit to be set in "sigs".
91
 */
92
void
93
psignals(void)
94
{
95
	int tsignals;
96
97
2
	if ((tsignals = sigs) == 0)
98
		return;
99
1
	sigs = 0;
100
101
1
	if (tsignals & S_STOP) {
102
		/*
103
		 * Clean up the terminal.
104
		 */
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);
113
		/*
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.
118
		 */
119
		lsignal(SIGTSTP, stop);
120
		raw_mode(1);
121
		init();
122
		screen_trashed = 1;
123
		tsignals |= S_WINCH;
124
	}
125
1
	if (tsignals & S_WINCH) {
126
		int old_width, old_height;
127
		/*
128
		 * Re-execute scrsize() to read the new window size.
129
		 */
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;
138
		}
139
	}
140
1
	if (tsignals & S_INTERRUPT) {
141
1
		ring_bell();
142
1
		if (quit_on_intr)
143
			quit(QUIT_INTERRUPT);
144
	}
145
2
}
146
147
/*
148
 * Custom version of signal() that causes syscalls to be interrupted.
149
 */
150
void *
151
lsignal(int s, void (*a)(int))
152
{
153
312
	struct sigaction sa, osa;
154
155
156
	sa.sa_handler = a;
156
156
	sigemptyset(&sa.sa_mask);
157
156
	sa.sa_flags = 0;		/* don't restart system calls */
158
156
	if (sigaction(s, &sa, &osa) != 0)
159
		return (SIG_ERR);
160
156
	return (osa.sa_handler);
161
156
}