1/*	$NetBSD: sig.c,v 1.16 2011/07/28 00:46:06 christos Exp $	*/
2
3/*-
4 * Copyright (c) 1992, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include "config.h"
36#if !defined(lint) && !defined(SCCSID)
37#if 0
38static char sccsid[] = "@(#)sig.c	8.1 (Berkeley) 6/4/93";
39#else
40__RCSID("$NetBSD: sig.c,v 1.16 2011/07/28 00:46:06 christos Exp $");
41#endif
42#endif /* not lint && not SCCSID */
43
44/*
45 * sig.c: Signal handling stuff.
46 *	  our policy is to trap all signals, set a good state
47 *	  and pass the ball to our caller.
48 */
49#include "el.h"
50#include <stdlib.h>
51
52private EditLine *sel = NULL;
53
54private const int sighdl[] = {
55#define	_DO(a)	(a),
56	ALLSIGS
57#undef	_DO
58	- 1
59};
60
61private void sig_handler(int);
62
63/* sig_handler():
64 *	This is the handler called for all signals
65 *	XXX: we cannot pass any data so we just store the old editline
66 *	state in a private variable
67 */
68private void
69sig_handler(int signo)
70{
71	int i;
72	sigset_t nset, oset;
73
74	(void) sigemptyset(&nset);
75	(void) sigaddset(&nset, signo);
76	(void) sigprocmask(SIG_BLOCK, &nset, &oset);
77
78	sel->el_signal->sig_no = signo;
79
80	switch (signo) {
81	case SIGCONT:
82		tty_rawmode(sel);
83		if (ed_redisplay(sel, 0) == CC_REFRESH)
84			re_refresh(sel);
85		terminal__flush(sel);
86		break;
87
88	case SIGWINCH:
89		el_resize(sel);
90		break;
91
92	default:
93		tty_cookedmode(sel);
94		break;
95	}
96
97	for (i = 0; sighdl[i] != -1; i++)
98		if (signo == sighdl[i])
99			break;
100
101	(void) sigaction(signo, &sel->el_signal->sig_action[i], NULL);
102	sel->el_signal->sig_action[i].sa_handler = SIG_ERR;
103	sel->el_signal->sig_action[i].sa_flags = 0;
104	sigemptyset(&sel->el_signal->sig_action[i].sa_mask);
105	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
106	(void) kill(0, signo);
107}
108
109
110/* sig_init():
111 *	Initialize all signal stuff
112 */
113protected int
114sig_init(EditLine *el)
115{
116	size_t i;
117	sigset_t *nset, oset;
118
119	el->el_signal = el_malloc(sizeof(*el->el_signal));
120	if (el->el_signal == NULL)
121		return -1;
122
123	nset = &el->el_signal->sig_set;
124	(void) sigemptyset(nset);
125#define	_DO(a) (void) sigaddset(nset, a);
126	ALLSIGS
127#undef	_DO
128	(void) sigprocmask(SIG_BLOCK, nset, &oset);
129
130	for (i = 0; sighdl[i] != -1; i++) {
131		el->el_signal->sig_action[i].sa_handler = SIG_ERR;
132		el->el_signal->sig_action[i].sa_flags = 0;
133		sigemptyset(&el->el_signal->sig_action[i].sa_mask);
134	}
135
136	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
137
138	return 0;
139}
140
141
142/* sig_end():
143 *	Clear all signal stuff
144 */
145protected void
146sig_end(EditLine *el)
147{
148
149	el_free(el->el_signal);
150	el->el_signal = NULL;
151}
152
153
154/* sig_set():
155 *	set all the signal handlers
156 */
157protected void
158sig_set(EditLine *el)
159{
160	size_t i;
161	sigset_t oset;
162	struct sigaction osa, nsa;
163
164	nsa.sa_handler = sig_handler;
165	nsa.sa_flags = 0;
166	sigemptyset(&nsa.sa_mask);
167
168	(void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
169
170	for (i = 0; sighdl[i] != -1; i++) {
171		/* This could happen if we get interrupted */
172		if (sigaction(sighdl[i], &nsa, &osa) != -1 &&
173		    osa.sa_handler != sig_handler)
174			el->el_signal->sig_action[i] = osa;
175	}
176	sel = el;
177	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
178}
179
180
181/* sig_clr():
182 *	clear all the signal handlers
183 */
184protected void
185sig_clr(EditLine *el)
186{
187	size_t i;
188	sigset_t oset;
189
190	(void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
191
192	for (i = 0; sighdl[i] != -1; i++)
193		if (el->el_signal->sig_action[i].sa_handler != SIG_ERR)
194			(void)sigaction(sighdl[i],
195			    &el->el_signal->sig_action[i], NULL);
196
197	sel = NULL;		/* we are going to die if the handler is
198				 * called */
199	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
200}
201