1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
/* Copyright (C) 1991, 92, 94, 95, 96, 97 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 Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <signal.h>
#include <errno.h>
#include <stddef.h>
/* We use a wrapper handler to support SV_RESETHAND. */
static __sighandler_t wrapped_handlers[NSIG];
static sigset_t wrapped_masks[NSIG];
static void wrapper_handler __P ((int sig));
static inline int convert_mask __P ((sigset_t *set, const int mask));
static void
wrapper_handler (sig)
int sig;
{
int save;
struct sigaction act;
act.sa_handler = SIG_DFL;
act.sa_mask = wrapped_masks[sig];
act.sa_flags = 0;
save = errno;
(void) __sigaction (sig, &act, (struct sigaction *) NULL);
__set_errno (save);
(*wrapped_handlers[sig]) (sig);
}
static inline int
convert_mask (set, mask)
sigset_t *set;
const int mask;
{
register int sig;
if (sizeof (*set) == sizeof (mask))
*(int *) set = mask;
else if (sizeof (*set) == sizeof (unsigned long int))
*(unsigned long int *) set = (unsigned int) mask;
else
{
if (__sigemptyset (set) < 0)
return -1;
for (sig = 1; sig < NSIG && sig <= sizeof (mask) * 8; ++sig)
if ((mask & sigmask (sig)) && __sigaddset (set, sig) < 0)
return -1;
}
return 0;
}
/* 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 (sig, vec, ovec)
int sig;
const struct sigvec *vec;
struct sigvec *ovec;
{
struct sigaction old;
if (vec == NULL || !(vec->sv_flags & SV_RESETHAND))
{
struct sigaction new, *n;
if (vec == NULL)
n = NULL;
else
{
n = &new;
n->sa_handler = vec->sv_handler;
if (convert_mask (&n->sa_mask, vec->sv_mask) < 0)
return -1;
n->sa_flags = 0;
if (vec->sv_flags & SV_ONSTACK)
{
#ifdef SA_ONSTACK
n->sa_flags |= SA_ONSTACK;
#else
__set_errno (ENOSYS);
return -1;
#endif
}
#ifdef SA_RESTART
if (!(vec->sv_flags & SV_INTERRUPT))
n->sa_flags |= SA_RESTART;
#endif
}
if (__sigaction (sig, n, &old) < 0)
return -1;
}
else
{
struct sigaction wrapper;
wrapper.sa_handler = wrapper_handler;
wrapped_handlers[sig] = vec->sv_handler;
if (convert_mask (&wrapped_masks[sig], vec->sv_mask) < 0)
return -1;
if (__sigaction (sig, &wrapper, &old) < 0)
return -1;
}
if (ovec != NULL)
{
register int i;
int mask = 0;
if (sizeof (int) == sizeof (sigset_t))
mask = *(int *) &old.sa_mask;
else if (sizeof (unsigned long int) == sizeof (sigset_t))
mask = *(unsigned long int *) &old.sa_mask;
else
for (i = 1; i < NSIG && i <= sizeof (mask) * 8; ++i)
if (__sigismember (&old.sa_mask, i))
mask |= sigmask (i);
ovec->sv_mask = mask;
ovec->sv_flags = 0;
#ifdef SA_ONSTACK
if (old.sa_flags & SA_ONSTACK)
ovec->sv_flags |= SV_ONSTACK;
#endif
#ifdef SA_RESTART
if (!(old.sa_flags & SA_RESTART))
#endif
ovec->sv_flags |= SV_INTERRUPT;
if (old.sa_handler == wrapper_handler)
{
ovec->sv_flags |= SV_RESETHAND;
ovec->sv_handler = wrapped_handlers[sig];
}
else
ovec->sv_handler = old.sa_handler;
}
return 0;
}
weak_alias (__sigvec, sigvec)
|