cleanup exit status handling
[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  * $DragonFly: src/lib/libedit/sig.c,v 1.3 2003/11/12 20:21:29 eirikn Exp $
38  *
39  * @(#)sig.c    8.1 (Berkeley) 6/4/93
40  */
41
42 /*
43  * sig.c: Signal handling stuff.
44  *        our policy is to trap all signals, set a good state
45  *        and pass the ball to our caller.
46  */
47 #include "sys.h"
48 #include "el.h"
49 #include <stdlib.h>
50
51 private EditLine *sel = NULL;
52
53 private int sighdl[] = {
54 #define _DO(a)  (a),
55     ALLSIGS
56 #undef _DO
57     -1
58 };
59
60 private void sig_handler        (int);
61
62 /* sig_handler():
63  *      This is the handler called for all signals
64  *      XXX: we cannot pass any data so we just store the old editline
65  *      state in a private variable
66  */
67 private void
68 sig_handler(signo)
69     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     switch (signo) {
79     case SIGCONT:
80         tty_rawmode(sel);
81         if (ed_redisplay(sel, 0) == CC_REFRESH)
82             re_refresh(sel);
83         term__flush();
84         break;
85
86     case SIGWINCH:
87         el_resize(sel);
88         break;
89
90     default:
91         tty_cookedmode(sel);
92         break;
93     }
94
95     for (i = 0; sighdl[i] != -1; i++)
96         if (signo == sighdl[i])
97             break;
98
99     (void) signal(signo, sel->el_signal[i]);
100     (void) sigprocmask(SIG_SETMASK, &oset, NULL);
101     (void) kill(0, signo);
102 }
103
104
105 /* sig_init():
106  *      Initialize all signal stuff
107  */
108 protected int
109 sig_init(el)
110     EditLine *el;
111 {
112     int i;
113     sigset_t nset, oset;
114
115     (void) sigemptyset(&nset);
116 #define _DO(a) (void) sigaddset(&nset, a);
117     ALLSIGS
118 #undef _DO
119     (void) sigprocmask(SIG_BLOCK, &nset, &oset);
120
121 #define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(sig_t))
122
123     el->el_signal = (sig_t *) el_malloc(SIGSIZE);
124     for (i = 0; sighdl[i] != -1; i++)
125         el->el_signal[i] = SIG_ERR;
126
127     (void) sigprocmask(SIG_SETMASK, &oset, NULL);
128
129     return 0;
130 }
131
132
133 /* sig_end():
134  *      Clear all signal stuff
135  */
136 protected void
137 sig_end(el)
138     EditLine *el;
139 {
140     el_free((ptr_t) el->el_signal);
141     el->el_signal = NULL;
142 }
143
144
145 /* sig_set():
146  *      set all the signal handlers
147  */
148 protected void
149 sig_set(el)
150     EditLine *el;
151 {
152     int i;
153     sigset_t nset, oset;
154
155     (void) sigemptyset(&nset);
156 #define _DO(a) (void) sigaddset(&nset, a);
157     ALLSIGS
158 #undef _DO
159     (void) sigprocmask(SIG_BLOCK, &nset, &oset);
160
161     for (i = 0; sighdl[i] != -1; i++) {
162         sig_t s;
163         /* This could happen if we get interrupted */
164         if ((s = signal(sighdl[i], sig_handler)) != sig_handler)
165             el->el_signal[i] = s;
166     }
167     sel = el;
168     (void) sigprocmask(SIG_SETMASK, &oset, NULL);
169 }
170
171
172 /* sig_clr():
173  *      clear all the signal handlers
174  */
175 protected void
176 sig_clr(el)
177     EditLine *el;
178 {
179     int i;
180     sigset_t nset, oset;
181
182     (void) sigemptyset(&nset);
183 #define _DO(a) (void) sigaddset(&nset, a);
184     ALLSIGS
185 #undef _DO
186     (void) sigprocmask(SIG_BLOCK, &nset, &oset);
187
188     for (i = 0; sighdl[i] != -1; i++)
189         if (el->el_signal[i] != SIG_ERR)
190             (void) signal(sighdl[i], el->el_signal[i]);
191
192     sel = NULL; /* we are going to die if the handler is called */
193     (void) sigprocmask(SIG_SETMASK, &oset, NULL);
194 }