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