Update libedit from NetBSD.
[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. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * @(#)sig.c    8.1 (Berkeley) 6/4/93
33  * $NetBSD: sig.c,v 1.11 2003/08/07 16:44:33 agc Exp $
34  * $DragonFly: src/lib/libedit/sig.c,v 1.4 2005/11/13 11:58:30 corecode Exp $
35  */
36
37 #include "config.h"
38
39 /*
40  * sig.c: Signal handling stuff.
41  *        our policy is to trap all signals, set a good state
42  *        and pass the ball to our caller.
43  */
44 #include "el.h"
45 #include <stdlib.h>
46
47 private EditLine *sel = NULL;
48
49 private const int sighdl[] = {
50 #define _DO(a)  (a),
51         ALLSIGS
52 #undef  _DO
53         - 1
54 };
55
56 private void sig_handler(int);
57
58 /* sig_handler():
59  *      This is the handler called for all signals
60  *      XXX: we cannot pass any data so we just store the old editline
61  *      state in a private variable
62  */
63 private void
64 sig_handler(int signo)
65 {
66         int i;
67         sigset_t nset, oset;
68
69         (void) sigemptyset(&nset);
70         (void) sigaddset(&nset, signo);
71         (void) sigprocmask(SIG_BLOCK, &nset, &oset);
72
73         switch (signo) {
74         case SIGCONT:
75                 tty_rawmode(sel);
76                 if (ed_redisplay(sel, 0) == CC_REFRESH)
77                         re_refresh(sel);
78                 term__flush();
79                 break;
80
81         case SIGWINCH:
82                 el_resize(sel);
83                 break;
84
85         default:
86                 tty_cookedmode(sel);
87                 break;
88         }
89
90         for (i = 0; sighdl[i] != -1; i++)
91                 if (signo == sighdl[i])
92                         break;
93
94         (void) signal(signo, sel->el_signal[i]);
95         (void) sigprocmask(SIG_SETMASK, &oset, NULL);
96         (void) kill(0, signo);
97 }
98
99
100 /* sig_init():
101  *      Initialize all signal stuff
102  */
103 protected int
104 sig_init(EditLine *el)
105 {
106         int i;
107         sigset_t nset, oset;
108
109         (void) sigemptyset(&nset);
110 #define _DO(a) (void) sigaddset(&nset, a);
111         ALLSIGS
112 #undef  _DO
113             (void) sigprocmask(SIG_BLOCK, &nset, &oset);
114
115 #define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(el_signalhandler_t))
116
117         el->el_signal = (el_signalhandler_t *) el_malloc(SIGSIZE);
118         if (el->el_signal == NULL)
119                 return (-1);
120         for (i = 0; sighdl[i] != -1; i++)
121                 el->el_signal[i] = SIG_ERR;
122
123         (void) sigprocmask(SIG_SETMASK, &oset, NULL);
124
125         return (0);
126 }
127
128
129 /* sig_end():
130  *      Clear all signal stuff
131  */
132 protected void
133 sig_end(EditLine *el)
134 {
135
136         el_free((ptr_t) el->el_signal);
137         el->el_signal = NULL;
138 }
139
140
141 /* sig_set():
142  *      set all the signal handlers
143  */
144 protected void
145 sig_set(EditLine *el)
146 {
147         int i;
148         sigset_t nset, oset;
149
150         (void) sigemptyset(&nset);
151 #define _DO(a) (void) sigaddset(&nset, a);
152         ALLSIGS
153 #undef  _DO
154             (void) sigprocmask(SIG_BLOCK, &nset, &oset);
155
156         for (i = 0; sighdl[i] != -1; i++) {
157                 el_signalhandler_t s;
158                 /* This could happen if we get interrupted */
159                 if ((s = signal(sighdl[i], sig_handler)) != sig_handler)
160                         el->el_signal[i] = s;
161         }
162         sel = el;
163         (void) sigprocmask(SIG_SETMASK, &oset, NULL);
164 }
165
166
167 /* sig_clr():
168  *      clear all the signal handlers
169  */
170 protected void
171 sig_clr(EditLine *el)
172 {
173         int i;
174         sigset_t nset, oset;
175
176         (void) sigemptyset(&nset);
177 #define _DO(a) (void) sigaddset(&nset, a);
178         ALLSIGS
179 #undef  _DO
180             (void) sigprocmask(SIG_BLOCK, &nset, &oset);
181
182         for (i = 0; sighdl[i] != -1; i++)
183                 if (el->el_signal[i] != SIG_ERR)
184                         (void) signal(sighdl[i], el->el_signal[i]);
185
186         sel = NULL;             /* we are going to die if the handler is
187                                  * called */
188         (void) sigprocmask(SIG_SETMASK, &oset, NULL);
189 }