xref: /netbsd-src/lib/libedit/sig.c (revision f1d4de73532f32e868394bddd8c8d68a2871c56c)
1*f1d4de73Schristos /*	$NetBSD: sig.c,v 1.28 2024/12/18 15:38:52 christos Exp $	*/
22543e3e6Slukem 
36dc2f1dbScgd /*-
46dc2f1dbScgd  * Copyright (c) 1992, 1993
56dc2f1dbScgd  *	The Regents of the University of California.  All rights reserved.
66dc2f1dbScgd  *
76dc2f1dbScgd  * This code is derived from software contributed to Berkeley by
86dc2f1dbScgd  * Christos Zoulas of Cornell University.
96dc2f1dbScgd  *
106dc2f1dbScgd  * Redistribution and use in source and binary forms, with or without
116dc2f1dbScgd  * modification, are permitted provided that the following conditions
126dc2f1dbScgd  * are met:
136dc2f1dbScgd  * 1. Redistributions of source code must retain the above copyright
146dc2f1dbScgd  *    notice, this list of conditions and the following disclaimer.
156dc2f1dbScgd  * 2. Redistributions in binary form must reproduce the above copyright
166dc2f1dbScgd  *    notice, this list of conditions and the following disclaimer in the
176dc2f1dbScgd  *    documentation and/or other materials provided with the distribution.
18eb7c1594Sagc  * 3. Neither the name of the University nor the names of its contributors
196dc2f1dbScgd  *    may be used to endorse or promote products derived from this software
206dc2f1dbScgd  *    without specific prior written permission.
216dc2f1dbScgd  *
226dc2f1dbScgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
236dc2f1dbScgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
246dc2f1dbScgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
256dc2f1dbScgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
266dc2f1dbScgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
276dc2f1dbScgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
286dc2f1dbScgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
296dc2f1dbScgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
306dc2f1dbScgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
316dc2f1dbScgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
326dc2f1dbScgd  * SUCH DAMAGE.
336dc2f1dbScgd  */
346dc2f1dbScgd 
350e0ac6b7Schristos #include "config.h"
366dc2f1dbScgd #if !defined(lint) && !defined(SCCSID)
372543e3e6Slukem #if 0
386dc2f1dbScgd static char sccsid[] = "@(#)sig.c	8.1 (Berkeley) 6/4/93";
392543e3e6Slukem #else
40*f1d4de73Schristos __RCSID("$NetBSD: sig.c,v 1.28 2024/12/18 15:38:52 christos Exp $");
412543e3e6Slukem #endif
426dc2f1dbScgd #endif /* not lint && not SCCSID */
436dc2f1dbScgd 
446dc2f1dbScgd /*
456dc2f1dbScgd  * sig.c: Signal handling stuff.
466dc2f1dbScgd  *	  our policy is to trap all signals, set a good state
476dc2f1dbScgd  *	  and pass the ball to our caller.
486dc2f1dbScgd  */
49a539b892Schristos #include <errno.h>
50747f6811Schristos #include <stdlib.h>
51747f6811Schristos 
52747f6811Schristos #include "el.h"
53747f6811Schristos #include "common.h"
54c807fdffSchristos 
55469d44f8Schristos static EditLine *sel = NULL;
566dc2f1dbScgd 
57469d44f8Schristos static const int sighdl[] = {
586dc2f1dbScgd #define	_DO(a)	(a),
596dc2f1dbScgd 	ALLSIGS
606dc2f1dbScgd #undef	_DO
616dc2f1dbScgd 	- 1
626dc2f1dbScgd };
636dc2f1dbScgd 
64469d44f8Schristos static void sig_handler(int);
656dc2f1dbScgd 
666dc2f1dbScgd /* sig_handler():
676dc2f1dbScgd  *	This is the handler called for all signals
686dc2f1dbScgd  *	XXX: we cannot pass any data so we just store the old editline
696dc2f1dbScgd  *	state in a private variable
706dc2f1dbScgd  */
71469d44f8Schristos static void
72d30d584aSlukem sig_handler(int signo)
736dc2f1dbScgd {
745367da5fSchristos 	int i, save_errno;
756dc2f1dbScgd 	sigset_t nset, oset;
766dc2f1dbScgd 
775367da5fSchristos 	save_errno = errno;
786dc2f1dbScgd 	(void) sigemptyset(&nset);
796dc2f1dbScgd 	(void) sigaddset(&nset, signo);
806dc2f1dbScgd 	(void) sigprocmask(SIG_BLOCK, &nset, &oset);
816dc2f1dbScgd 
82e8bbf84cSchristos 	sel->el_signal->sig_no = signo;
83e8bbf84cSchristos 
846dc2f1dbScgd 	switch (signo) {
856dc2f1dbScgd 	case SIGCONT:
866dc2f1dbScgd 		tty_rawmode(sel);
876dc2f1dbScgd 		if (ed_redisplay(sel, 0) == CC_REFRESH)
886dc2f1dbScgd 			re_refresh(sel);
89e63c844aSchristos 		terminal__flush(sel);
906dc2f1dbScgd 		break;
916dc2f1dbScgd 
926dc2f1dbScgd 	case SIGWINCH:
936dc2f1dbScgd 		el_resize(sel);
946dc2f1dbScgd 		break;
956dc2f1dbScgd 
966dc2f1dbScgd 	default:
976dc2f1dbScgd 		tty_cookedmode(sel);
986dc2f1dbScgd 		break;
996dc2f1dbScgd 	}
1006dc2f1dbScgd 
1016dc2f1dbScgd 	for (i = 0; sighdl[i] != -1; i++)
1026dc2f1dbScgd 		if (signo == sighdl[i])
1036dc2f1dbScgd 			break;
1046dc2f1dbScgd 
105d25b6758Schristos 	(void) sigaction(signo, &sel->el_signal->sig_action[i], NULL);
106d25b6758Schristos 	sel->el_signal->sig_action[i].sa_handler = SIG_ERR;
107d25b6758Schristos 	sel->el_signal->sig_action[i].sa_flags = 0;
108d25b6758Schristos 	sigemptyset(&sel->el_signal->sig_action[i].sa_mask);
1096dc2f1dbScgd 	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
1106dc2f1dbScgd 	(void) kill(0, signo);
1115367da5fSchristos 	errno = save_errno;
1126dc2f1dbScgd }
1136dc2f1dbScgd 
1146dc2f1dbScgd 
1156dc2f1dbScgd /* sig_init():
1166dc2f1dbScgd  *	Initialize all signal stuff
1176dc2f1dbScgd  */
118a2d6b270Schristos libedit_private int
119d30d584aSlukem sig_init(EditLine *el)
1206dc2f1dbScgd {
121d25b6758Schristos 	size_t i;
122d25b6758Schristos 	sigset_t *nset, oset;
1236dc2f1dbScgd 
124d25b6758Schristos 	el->el_signal = el_malloc(sizeof(*el->el_signal));
125d25b6758Schristos 	if (el->el_signal == NULL)
126d25b6758Schristos 		return -1;
127d25b6758Schristos 
128d25b6758Schristos 	nset = &el->el_signal->sig_set;
129d25b6758Schristos 	(void) sigemptyset(nset);
130d25b6758Schristos #define	_DO(a) (void) sigaddset(nset, a);
1316dc2f1dbScgd 	ALLSIGS
1326dc2f1dbScgd #undef	_DO
133d25b6758Schristos 	(void) sigprocmask(SIG_BLOCK, nset, &oset);
1346dc2f1dbScgd 
135d25b6758Schristos 	for (i = 0; sighdl[i] != -1; i++) {
136d25b6758Schristos 		el->el_signal->sig_action[i].sa_handler = SIG_ERR;
137d25b6758Schristos 		el->el_signal->sig_action[i].sa_flags = 0;
138d25b6758Schristos 		sigemptyset(&el->el_signal->sig_action[i].sa_mask);
139d25b6758Schristos 	}
1406dc2f1dbScgd 
1416dc2f1dbScgd 	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
1426dc2f1dbScgd 
143d25b6758Schristos 	return 0;
1446dc2f1dbScgd }
1456dc2f1dbScgd 
1466dc2f1dbScgd 
1476dc2f1dbScgd /* sig_end():
1486dc2f1dbScgd  *	Clear all signal stuff
1496dc2f1dbScgd  */
150a2d6b270Schristos libedit_private void
151d30d584aSlukem sig_end(EditLine *el)
1526dc2f1dbScgd {
153d30d584aSlukem 
154a13cd756Schristos 	el_free(el->el_signal);
1556dc2f1dbScgd 	el->el_signal = NULL;
1566dc2f1dbScgd }
1576dc2f1dbScgd 
1586dc2f1dbScgd 
1596dc2f1dbScgd /* sig_set():
1606dc2f1dbScgd  *	set all the signal handlers
1616dc2f1dbScgd  */
162a2d6b270Schristos libedit_private void
163d30d584aSlukem sig_set(EditLine *el)
1646dc2f1dbScgd {
165d25b6758Schristos 	size_t i;
166d25b6758Schristos 	sigset_t oset;
167d25b6758Schristos 	struct sigaction osa, nsa;
1686dc2f1dbScgd 
169d25b6758Schristos 	nsa.sa_handler = sig_handler;
170*f1d4de73Schristos 	nsa.sa_flags = SA_ONSTACK;
171d25b6758Schristos 	sigemptyset(&nsa.sa_mask);
172d25b6758Schristos 
1730428f1e1Schristos 	sel = el;
174d25b6758Schristos 	(void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
1756dc2f1dbScgd 
1766dc2f1dbScgd 	for (i = 0; sighdl[i] != -1; i++) {
1776dc2f1dbScgd 		/* This could happen if we get interrupted */
178d25b6758Schristos 		if (sigaction(sighdl[i], &nsa, &osa) != -1 &&
179d25b6758Schristos 		    osa.sa_handler != sig_handler)
180d25b6758Schristos 			el->el_signal->sig_action[i] = osa;
1816dc2f1dbScgd 	}
1826dc2f1dbScgd 	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
1836dc2f1dbScgd }
1846dc2f1dbScgd 
1856dc2f1dbScgd 
1866dc2f1dbScgd /* sig_clr():
1876dc2f1dbScgd  *	clear all the signal handlers
1886dc2f1dbScgd  */
189a2d6b270Schristos libedit_private void
190d30d584aSlukem sig_clr(EditLine *el)
1916dc2f1dbScgd {
192d25b6758Schristos 	size_t i;
193d25b6758Schristos 	sigset_t oset;
1946dc2f1dbScgd 
195d25b6758Schristos 	(void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
1966dc2f1dbScgd 
1976dc2f1dbScgd 	for (i = 0; sighdl[i] != -1; i++)
198d25b6758Schristos 		if (el->el_signal->sig_action[i].sa_handler != SIG_ERR)
199d25b6758Schristos 			(void)sigaction(sighdl[i],
200d25b6758Schristos 			    &el->el_signal->sig_action[i], NULL);
2016dc2f1dbScgd 
2026dc2f1dbScgd 	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
2036dc2f1dbScgd }
204