11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1992, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * This code is derived from software contributed to Berkeley by
61573Srgrimes * Christos Zoulas of Cornell University.
71573Srgrimes *
81573Srgrimes * Redistribution and use in source and binary forms, with or without
91573Srgrimes * modification, are permitted provided that the following conditions
101573Srgrimes * are met:
111573Srgrimes * 1. Redistributions of source code must retain the above copyright
121573Srgrimes *    notice, this list of conditions and the following disclaimer.
131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141573Srgrimes *    notice, this list of conditions and the following disclaimer in the
151573Srgrimes *    documentation and/or other materials provided with the distribution.
16148834Sstefanf * 3. Neither the name of the University nor the names of its contributors
171573Srgrimes *    may be used to endorse or promote products derived from this software
181573Srgrimes *    without specific prior written permission.
191573Srgrimes *
201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301573Srgrimes * SUCH DAMAGE.
3184260Sobrien *
32238378Spfg *	$NetBSD: sig.c,v 1.15 2009/02/19 15:20:22 christos Exp $
331573Srgrimes */
341573Srgrimes
351573Srgrimes#if !defined(lint) && !defined(SCCSID)
361573Srgrimesstatic char sccsid[] = "@(#)sig.c	8.1 (Berkeley) 6/4/93";
371573Srgrimes#endif /* not lint && not SCCSID */
3884260Sobrien#include <sys/cdefs.h>
3984260Sobrien__FBSDID("$FreeBSD$");
401573Srgrimes
411573Srgrimes/*
421573Srgrimes * sig.c: Signal handling stuff.
431573Srgrimes *	  our policy is to trap all signals, set a good state
441573Srgrimes *	  and pass the ball to our caller.
451573Srgrimes */
461573Srgrimes#include "sys.h"
471573Srgrimes#include "el.h"
481573Srgrimes#include <stdlib.h>
491573Srgrimes
501573Srgrimesprivate EditLine *sel = NULL;
511573Srgrimes
5284260Sobrienprivate const int sighdl[] = {
5384260Sobrien#define	_DO(a)	(a),
5484260Sobrien	ALLSIGS
5584260Sobrien#undef	_DO
5684260Sobrien	- 1
571573Srgrimes};
581573Srgrimes
5984260Sobrienprivate void sig_handler(int);
601573Srgrimes
611573Srgrimes/* sig_handler():
621573Srgrimes *	This is the handler called for all signals
631573Srgrimes *	XXX: we cannot pass any data so we just store the old editline
641573Srgrimes *	state in a private variable
651573Srgrimes */
661573Srgrimesprivate void
6784260Sobriensig_handler(int signo)
681573Srgrimes{
6984260Sobrien	int i;
7084260Sobrien	sigset_t nset, oset;
711573Srgrimes
7284260Sobrien	(void) sigemptyset(&nset);
7384260Sobrien	(void) sigaddset(&nset, signo);
7484260Sobrien	(void) sigprocmask(SIG_BLOCK, &nset, &oset);
751573Srgrimes
76238378Spfg	sel->el_signal->sig_no = signo;
77238378Spfg
7884260Sobrien	switch (signo) {
7984260Sobrien	case SIGCONT:
8084260Sobrien		tty_rawmode(sel);
8184260Sobrien		if (ed_redisplay(sel, 0) == CC_REFRESH)
8284260Sobrien			re_refresh(sel);
83237448Spfg		term__flush(sel);
8484260Sobrien		break;
851573Srgrimes
8684260Sobrien	case SIGWINCH:
8784260Sobrien		el_resize(sel);
8884260Sobrien		break;
891573Srgrimes
9084260Sobrien	default:
9184260Sobrien		tty_cookedmode(sel);
9284260Sobrien		break;
9384260Sobrien	}
941573Srgrimes
9584260Sobrien	for (i = 0; sighdl[i] != -1; i++)
9684260Sobrien		if (signo == sighdl[i])
9784260Sobrien			break;
981573Srgrimes
99237448Spfg	(void) sigaction(signo, &sel->el_signal->sig_action[i], NULL);
100237448Spfg	sel->el_signal->sig_action[i].sa_handler = SIG_ERR;
101237448Spfg	sel->el_signal->sig_action[i].sa_flags = 0;
102237448Spfg	sigemptyset(&sel->el_signal->sig_action[i].sa_mask);
10384260Sobrien	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
10484260Sobrien	(void) kill(0, signo);
1051573Srgrimes}
1061573Srgrimes
1071573Srgrimes
1081573Srgrimes/* sig_init():
1091573Srgrimes *	Initialize all signal stuff
1101573Srgrimes */
1111573Srgrimesprotected int
11284260Sobriensig_init(EditLine *el)
1131573Srgrimes{
114237448Spfg	size_t i;
115237448Spfg	sigset_t *nset, oset;
1161573Srgrimes
117237448Spfg	el->el_signal = el_malloc(sizeof(*el->el_signal));
118237448Spfg	if (el->el_signal == NULL)
119237448Spfg		return -1;
120237448Spfg
121237448Spfg	nset = &el->el_signal->sig_set;
122237448Spfg	(void) sigemptyset(nset);
123237448Spfg#define	_DO(a) (void) sigaddset(nset, a);
12484260Sobrien	ALLSIGS
12584260Sobrien#undef	_DO
126237448Spfg	(void) sigprocmask(SIG_BLOCK, nset, &oset);
1271573Srgrimes
128237448Spfg	for (i = 0; sighdl[i] != -1; i++) {
129237448Spfg		el->el_signal->sig_action[i].sa_handler = SIG_ERR;
130237448Spfg		el->el_signal->sig_action[i].sa_flags = 0;
131237448Spfg		sigemptyset(&el->el_signal->sig_action[i].sa_mask);
132237448Spfg	}
1331573Srgrimes
13484260Sobrien	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
1351573Srgrimes
136237448Spfg	return 0;
1371573Srgrimes}
1381573Srgrimes
1391573Srgrimes
1401573Srgrimes/* sig_end():
1411573Srgrimes *	Clear all signal stuff
1421573Srgrimes */
1431573Srgrimesprotected void
14484260Sobriensig_end(EditLine *el)
1451573Srgrimes{
14684260Sobrien
14784260Sobrien	el_free((ptr_t) el->el_signal);
14884260Sobrien	el->el_signal = NULL;
1491573Srgrimes}
1501573Srgrimes
1511573Srgrimes
1521573Srgrimes/* sig_set():
1531573Srgrimes *	set all the signal handlers
1541573Srgrimes */
1551573Srgrimesprotected void
15684260Sobriensig_set(EditLine *el)
1571573Srgrimes{
158237448Spfg	size_t i;
159237448Spfg	sigset_t oset;
160237448Spfg	struct sigaction osa, nsa;
1611573Srgrimes
162237448Spfg	nsa.sa_handler = sig_handler;
163238378Spfg	nsa.sa_flags = 0;
164237448Spfg	sigemptyset(&nsa.sa_mask);
1651573Srgrimes
166237448Spfg	(void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
167237448Spfg
16884260Sobrien	for (i = 0; sighdl[i] != -1; i++) {
16984260Sobrien		/* This could happen if we get interrupted */
170237448Spfg		if (sigaction(sighdl[i], &nsa, &osa) != -1 &&
171237448Spfg		    osa.sa_handler != sig_handler)
172237448Spfg			el->el_signal->sig_action[i] = osa;
17384260Sobrien	}
17484260Sobrien	sel = el;
17584260Sobrien	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
1761573Srgrimes}
1771573Srgrimes
1781573Srgrimes
1791573Srgrimes/* sig_clr():
1801573Srgrimes *	clear all the signal handlers
1811573Srgrimes */
1821573Srgrimesprotected void
18384260Sobriensig_clr(EditLine *el)
1841573Srgrimes{
185237448Spfg	size_t i;
186237448Spfg	sigset_t oset;
1871573Srgrimes
188237448Spfg	(void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
1891573Srgrimes
19084260Sobrien	for (i = 0; sighdl[i] != -1; i++)
191237448Spfg		if (el->el_signal->sig_action[i].sa_handler != SIG_ERR)
192237448Spfg			(void)sigaction(sighdl[i],
193237448Spfg			    &el->el_signal->sig_action[i], NULL);
1941573Srgrimes
19584260Sobrien	sel = NULL;		/* we are going to die if the handler is
19684260Sobrien				 * called */
197237448Spfg	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
1981573Srgrimes}
199