| 1 | /* ABI compatibility for obsolete sigvec function from 4.2BSD. | 
|---|
| 2 | Copyright (C) 1991-2020 Free Software Foundation, Inc. | 
|---|
| 3 | This file is part of the GNU C Library. | 
|---|
| 4 |  | 
|---|
| 5 | The GNU C Library is free software; you can redistribute it and/or | 
|---|
| 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. | 
|---|
| 9 |  | 
|---|
| 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 | 
|---|
| 13 | Lesser General Public License for more details. | 
|---|
| 14 |  | 
|---|
| 15 | You should have received a copy of the GNU Lesser General Public | 
|---|
| 16 | License along with the GNU C Library; if not, see | 
|---|
| 17 | <https://www.gnu.org/licenses/>.  */ | 
|---|
| 18 |  | 
|---|
| 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 |  | 
|---|
| 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 | 
|---|
| 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 | 
|---|
| 182 | sigvec_wrapper_handler (int sig) | 
|---|
| 183 | { | 
|---|
| 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); | 
|---|
| 199 | } | 
|---|
| 200 | # endif  /* No SA_RESETHAND.  */ | 
|---|
| 201 |  | 
|---|
| 202 | #endif  /* SHLIB_COMPAT */ | 
|---|
| 203 |  | 
|---|