/* $NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $ */ /*- * Copyright (c) 2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Luke Mewburn. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #if HAVE_NBTOOL_CONFIG_H #include "nbtool_config.h" #endif #include #if defined(LIBC_SCCS) && !defined(lint) __RCSID("$NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $"); #endif #include #include #include #include #include #if ! HAVE_RAISE_DEFAULT_SIGNAL /* * raise_default_signal sig * Raise the default signal handler for sig, by * - block all signals * - set the signal handler to SIG_DFL * - raise the signal * - unblock the signal to deliver it * * The original signal mask and signal handler is restored on exit * (whether successful or not). * * Returns 0 on success, or -1 on failure with errno set to * on of the values for sigemptyset(), sigaddset(), sigprocmask(), * sigaction(), or raise(). */ int raise_default_signal(int sig) { struct sigaction origact, act; sigset_t origmask, fullmask, mask; int retval, oerrno; retval = -1; /* Setup data structures */ /* XXX memset(3) isn't async-safe according to signal(7) */ (void)memset(&act, 0, sizeof(act)); act.sa_handler = SIG_DFL; act.sa_flags = 0; if ((sigemptyset(&act.sa_mask) == -1) || (sigfillset(&fullmask) == -1) || (sigemptyset(&mask) == -1) || (sigaddset(&mask, sig) == -1)) goto restore_none; /* Block all signals */ if (sigprocmask(SIG_BLOCK, &fullmask, &origmask) == -1) goto restore_none; /* (use 'goto restore_mask' to restore state) */ /* Enable the SIG_DFL handler */ if (sigaction(sig, &act, &origact) == -1) goto restore_mask; /* (use 'goto restore_act' to restore state) */ /* Raise the signal, and unblock the signal to deliver it */ if ((raise(sig) == -1) || (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)) goto restore_act; /* Flag successful raise() */ retval = 0; /* Restore the original handler */ restore_act: oerrno = errno; (void)sigaction(sig, &origact, NULL); errno = oerrno; /* Restore the original mask */ restore_mask: oerrno = errno; (void)sigprocmask(SIG_SETMASK, &origmask, NULL); errno = oerrno; restore_none: return retval; } #endif /* ! HAVE_RAISE_DEFAULT_SIGNAL */