]>
Commit | Line | Data |
---|---|---|
0781a777 | 1 | /* ABI compatibility for obsolete sigvec function from 4.2BSD. |
04277e02 | 2 | Copyright (C) 1991-2019 Free Software Foundation, Inc. |
478b92f0 | 3 | This file is part of the GNU C Library. |
28f540f4 | 4 | |
478b92f0 | 5 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
28f540f4 | 9 | |
478b92f0 UD |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
28f540f4 | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
28f540f4 | 18 | |
0781a777 RM |
19 | #include <shlib-compat.h> |
20 | ||
21 | #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21) | |
22 | ||
23 | # include <signal.h> | |
24 | # include <errno.h> | |
25 | # include <stddef.h> | |
26 | ||
27 | ||
28 | /* These are the struct sigvec and SV_* bit definitions that | |
29 | used to be in <signal.h>. The whole interface now exists | |
30 | solely for ABI compatibility, so it can just be here. */ | |
31 | struct sigvec | |
32 | { | |
33 | __sighandler_t sv_handler; /* Signal handler. */ | |
34 | int sv_mask; /* Mask of signals to be blocked. */ | |
35 | ||
36 | int sv_flags; /* Flags (see below). */ | |
37 | }; | |
38 | # define SV_ONSTACK (1 << 0)/* Take the signal on the signal stack. */ | |
39 | # define SV_INTERRUPT (1 << 1)/* Do not restart system calls. */ | |
40 | # define SV_RESETHAND (1 << 2)/* Reset handler to SIG_DFL on receipt. */ | |
41 | ||
42 | ||
43 | /* Include macros to convert between `sigset_t' and old-style mask. */ | |
44 | # include <sigset-cvt-mask.h> | |
45 | ||
46 | # ifndef SA_RESETHAND | |
47 | /* When sigaction lacks the extension bit for it, | |
48 | we use a wrapper handler to support SV_RESETHAND. */ | |
49 | struct sigvec_wrapper_data | |
50 | { | |
51 | __sighandler_t sw_handler; | |
52 | unsigned int sw_mask; | |
53 | }; | |
54 | ||
55 | static void sigvec_wrapper_handler (int sig) __THROW; | |
56 | ||
57 | static struct sigvec_wrapper_data sigvec_wrapper_data[NSIG]; | |
58 | # endif | |
59 | ||
28f540f4 RM |
60 | |
61 | /* If VEC is non-NULL, set the handler for SIG to the `sv_handler' member | |
62 | of VEC. The signals in `sv_mask' will be blocked while the handler runs. | |
63 | If the SV_RESETHAND bit is set in `sv_flags', the handler for SIG will be | |
64 | reset to SIG_DFL before `sv_handler' is entered. If OVEC is non-NULL, | |
65 | it is filled in with the old information for SIG. */ | |
66 | int | |
0781a777 RM |
67 | __sigvec (int sig, |
68 | const struct sigvec *vec, | |
69 | struct sigvec *ovec) | |
70 | { | |
71 | struct sigaction old; | |
72 | ||
73 | # ifndef SA_RESETHAND | |
74 | if (vec == NULL || !(vec->sv_flags & SV_RESETHAND)) | |
75 | # endif | |
76 | { | |
77 | struct sigaction new, *n; | |
78 | ||
79 | if (vec == NULL) | |
80 | n = NULL; | |
81 | else | |
82 | { | |
83 | __sighandler_t handler; | |
84 | unsigned int mask; | |
85 | unsigned int sv_flags; | |
86 | unsigned int sa_flags; | |
87 | ||
88 | handler = vec->sv_handler; | |
89 | mask = vec->sv_mask; | |
90 | sv_flags = vec->sv_flags; | |
91 | sa_flags = 0; | |
92 | if (sv_flags & SV_ONSTACK) | |
93 | { | |
94 | # ifdef SA_ONSTACK | |
95 | sa_flags |= SA_ONSTACK; | |
96 | # else | |
97 | __set_errno (ENOSYS); | |
98 | return -1; | |
99 | # endif | |
100 | } | |
101 | # ifdef SA_RESTART | |
102 | if (!(sv_flags & SV_INTERRUPT)) | |
103 | sa_flags |= SA_RESTART; | |
104 | # endif | |
105 | # ifdef SA_RESETHAND | |
106 | if (sv_flags & SV_RESETHAND) | |
107 | sa_flags |= SA_RESETHAND; | |
108 | # endif | |
109 | n = &new; | |
110 | new.sa_handler = handler; | |
111 | if (sigset_set_old_mask (&new.sa_mask, mask) < 0) | |
112 | return -1; | |
113 | new.sa_flags = sa_flags; | |
114 | } | |
115 | ||
116 | if (__sigaction (sig, n, &old) < 0) | |
117 | return -1; | |
118 | } | |
119 | # ifndef SA_RESETHAND | |
120 | else | |
121 | { | |
122 | __sighandler_t handler; | |
123 | unsigned int mask; | |
124 | struct sigvec_wrapper_data *data; | |
125 | struct sigaction wrapper; | |
126 | ||
127 | handler = vec->sv_handler; | |
128 | mask = (unsigned int)vec->sv_mask; | |
129 | data = &sigvec_wrapper_data[sig]; | |
130 | wrapper.sa_handler = sigvec_wrapper_handler; | |
131 | /* FIXME: should we set wrapper.sa_mask, wrapper.sa_flags?? */ | |
132 | data->sw_handler = handler; | |
133 | data->sw_mask = mask; | |
134 | ||
135 | if (__sigaction (sig, &wrapper, &old) < 0) | |
136 | return -1; | |
137 | } | |
138 | # endif | |
139 | ||
140 | if (ovec != NULL) | |
141 | { | |
142 | __sighandler_t handler; | |
143 | unsigned int sv_flags; | |
144 | unsigned int sa_flags; | |
145 | unsigned int mask; | |
146 | ||
147 | handler = old.sa_handler; | |
148 | sv_flags = 0; | |
149 | sa_flags = old.sa_flags; | |
150 | # ifndef SA_RESETHAND | |
151 | if (handler == sigvec_wrapper_handler) | |
152 | { | |
153 | handler = sigvec_wrapper_data[sig].sw_handler; | |
154 | /* should we use data->sw_mask?? */ | |
155 | sv_flags |= SV_RESETHAND; | |
156 | } | |
157 | # else | |
158 | if (sa_flags & SA_RESETHAND) | |
159 | sv_flags |= SV_RESETHAND; | |
160 | # endif | |
161 | mask = sigset_get_old_mask (&old.sa_mask); | |
162 | # ifdef SA_ONSTACK | |
163 | if (sa_flags & SA_ONSTACK) | |
164 | sv_flags |= SV_ONSTACK; | |
165 | # endif | |
166 | # ifdef SA_RESTART | |
167 | if (!(sa_flags & SA_RESTART)) | |
168 | # endif | |
169 | sv_flags |= SV_INTERRUPT; | |
170 | ovec->sv_handler = handler; | |
171 | ovec->sv_mask = (int)mask; | |
172 | ovec->sv_flags = (int)sv_flags; | |
173 | } | |
174 | ||
175 | return 0; | |
176 | } | |
177 | ||
178 | compat_symbol (libc, __sigvec, sigvec, GLIBC_2_0); | |
179 | ||
180 | # ifndef SA_RESETHAND | |
181 | static void | |
9d46370c | 182 | sigvec_wrapper_handler (int sig) |
28f540f4 | 183 | { |
0781a777 RM |
184 | struct sigvec_wrapper_data *data; |
185 | struct sigaction act; | |
186 | int save; | |
187 | __sighandler_t handler; | |
188 | ||
189 | data = &sigvec_wrapper_data[sig]; | |
190 | act.sa_handler = SIG_DFL; | |
191 | act.sa_flags = 0; | |
192 | sigset_set_old_mask (&act.sa_mask, data->sw_mask); | |
193 | handler = data->sw_handler; | |
194 | save = errno; | |
195 | (void) __sigaction (sig, &act, (struct sigaction *) NULL); | |
196 | __set_errno (save); | |
197 | ||
198 | (*handler) (sig); | |
28f540f4 | 199 | } |
0781a777 | 200 | # endif /* No SA_RESETHAND. */ |
28f540f4 | 201 | |
0781a777 | 202 | #endif /* SHLIB_COMPAT */ |