123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- /* ABI compatibility for obsolete sigvec function from 4.2BSD.
- Copyright (C) 1991-2019 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
- #include <shlib-compat.h>
- #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21)
- # include <signal.h>
- # include <errno.h>
- # include <stddef.h>
- /* These are the struct sigvec and SV_* bit definitions that
- used to be in <signal.h>. The whole interface now exists
- solely for ABI compatibility, so it can just be here. */
- struct sigvec
- {
- __sighandler_t sv_handler; /* Signal handler. */
- int sv_mask; /* Mask of signals to be blocked. */
- int sv_flags; /* Flags (see below). */
- };
- # define SV_ONSTACK (1 << 0)/* Take the signal on the signal stack. */
- # define SV_INTERRUPT (1 << 1)/* Do not restart system calls. */
- # define SV_RESETHAND (1 << 2)/* Reset handler to SIG_DFL on receipt. */
- /* Include macros to convert between `sigset_t' and old-style mask. */
- # include <sigset-cvt-mask.h>
- # ifndef SA_RESETHAND
- /* When sigaction lacks the extension bit for it,
- we use a wrapper handler to support SV_RESETHAND. */
- struct sigvec_wrapper_data
- {
- __sighandler_t sw_handler;
- unsigned int sw_mask;
- };
- static void sigvec_wrapper_handler (int sig) __THROW;
- static struct sigvec_wrapper_data sigvec_wrapper_data[NSIG];
- # endif
- /* If VEC is non-NULL, set the handler for SIG to the `sv_handler' member
- of VEC. The signals in `sv_mask' will be blocked while the handler runs.
- If the SV_RESETHAND bit is set in `sv_flags', the handler for SIG will be
- reset to SIG_DFL before `sv_handler' is entered. If OVEC is non-NULL,
- it is filled in with the old information for SIG. */
- int
- __sigvec (int sig,
- const struct sigvec *vec,
- struct sigvec *ovec)
- {
- struct sigaction old;
- # ifndef SA_RESETHAND
- if (vec == NULL || !(vec->sv_flags & SV_RESETHAND))
- # endif
- {
- struct sigaction new, *n;
- if (vec == NULL)
- n = NULL;
- else
- {
- __sighandler_t handler;
- unsigned int mask;
- unsigned int sv_flags;
- unsigned int sa_flags;
- handler = vec->sv_handler;
- mask = vec->sv_mask;
- sv_flags = vec->sv_flags;
- sa_flags = 0;
- if (sv_flags & SV_ONSTACK)
- {
- # ifdef SA_ONSTACK
- sa_flags |= SA_ONSTACK;
- # else
- __set_errno (ENOSYS);
- return -1;
- # endif
- }
- # ifdef SA_RESTART
- if (!(sv_flags & SV_INTERRUPT))
- sa_flags |= SA_RESTART;
- # endif
- # ifdef SA_RESETHAND
- if (sv_flags & SV_RESETHAND)
- sa_flags |= SA_RESETHAND;
- # endif
- n = &new;
- new.sa_handler = handler;
- if (sigset_set_old_mask (&new.sa_mask, mask) < 0)
- return -1;
- new.sa_flags = sa_flags;
- }
- if (__sigaction (sig, n, &old) < 0)
- return -1;
- }
- # ifndef SA_RESETHAND
- else
- {
- __sighandler_t handler;
- unsigned int mask;
- struct sigvec_wrapper_data *data;
- struct sigaction wrapper;
- handler = vec->sv_handler;
- mask = (unsigned int)vec->sv_mask;
- data = &sigvec_wrapper_data[sig];
- wrapper.sa_handler = sigvec_wrapper_handler;
- /* FIXME: should we set wrapper.sa_mask, wrapper.sa_flags?? */
- data->sw_handler = handler;
- data->sw_mask = mask;
- if (__sigaction (sig, &wrapper, &old) < 0)
- return -1;
- }
- # endif
- if (ovec != NULL)
- {
- __sighandler_t handler;
- unsigned int sv_flags;
- unsigned int sa_flags;
- unsigned int mask;
- handler = old.sa_handler;
- sv_flags = 0;
- sa_flags = old.sa_flags;
- # ifndef SA_RESETHAND
- if (handler == sigvec_wrapper_handler)
- {
- handler = sigvec_wrapper_data[sig].sw_handler;
- /* should we use data->sw_mask?? */
- sv_flags |= SV_RESETHAND;
- }
- # else
- if (sa_flags & SA_RESETHAND)
- sv_flags |= SV_RESETHAND;
- # endif
- mask = sigset_get_old_mask (&old.sa_mask);
- # ifdef SA_ONSTACK
- if (sa_flags & SA_ONSTACK)
- sv_flags |= SV_ONSTACK;
- # endif
- # ifdef SA_RESTART
- if (!(sa_flags & SA_RESTART))
- # endif
- sv_flags |= SV_INTERRUPT;
- ovec->sv_handler = handler;
- ovec->sv_mask = (int)mask;
- ovec->sv_flags = (int)sv_flags;
- }
- return 0;
- }
- compat_symbol (libc, __sigvec, sigvec, GLIBC_2_0);
- # ifndef SA_RESETHAND
- static void
- sigvec_wrapper_handler (int sig)
- {
- struct sigvec_wrapper_data *data;
- struct sigaction act;
- int save;
- __sighandler_t handler;
- data = &sigvec_wrapper_data[sig];
- act.sa_handler = SIG_DFL;
- act.sa_flags = 0;
- sigset_set_old_mask (&act.sa_mask, data->sw_mask);
- handler = data->sw_handler;
- save = errno;
- (void) __sigaction (sig, &act, (struct sigaction *) NULL);
- __set_errno (save);
- (*handler) (sig);
- }
- # endif /* No SA_RESETHAND. */
- #endif /* SHLIB_COMPAT */
|