1 /* $NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Luke Mewburn. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #if HAVE_NBTOOL_CONFIG_H 33 #include "nbtool_config.h" 34 #endif 35 36 #include <sys/cdefs.h> 37 #if defined(LIBC_SCCS) && !defined(lint) 38 __RCSID("$NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $"); 39 #endif 40 41 #include <errno.h> 42 #include <signal.h> 43 #include <stdio.h> 44 #include <string.h> 45 #include <util.h> 46 47 #if ! HAVE_RAISE_DEFAULT_SIGNAL 48 /* 49 * raise_default_signal sig 50 * Raise the default signal handler for sig, by 51 * - block all signals 52 * - set the signal handler to SIG_DFL 53 * - raise the signal 54 * - unblock the signal to deliver it 55 * 56 * The original signal mask and signal handler is restored on exit 57 * (whether successful or not). 58 * 59 * Returns 0 on success, or -1 on failure with errno set to 60 * on of the values for sigemptyset(), sigaddset(), sigprocmask(), 61 * sigaction(), or raise(). 62 */ 63 int 64 raise_default_signal(int sig) 65 { 66 struct sigaction origact, act; 67 sigset_t origmask, fullmask, mask; 68 int retval, oerrno; 69 70 retval = -1; 71 72 /* Setup data structures */ 73 /* XXX memset(3) isn't async-safe according to signal(7) */ 74 (void)memset(&act, 0, sizeof(act)); 75 act.sa_handler = SIG_DFL; 76 act.sa_flags = 0; 77 if ((sigemptyset(&act.sa_mask) == -1) || 78 (sigfillset(&fullmask) == -1) || 79 (sigemptyset(&mask) == -1) || 80 (sigaddset(&mask, sig) == -1)) 81 goto restore_none; 82 83 /* Block all signals */ 84 if (sigprocmask(SIG_BLOCK, &fullmask, &origmask) == -1) 85 goto restore_none; 86 /* (use 'goto restore_mask' to restore state) */ 87 88 /* Enable the SIG_DFL handler */ 89 if (sigaction(sig, &act, &origact) == -1) 90 goto restore_mask; 91 /* (use 'goto restore_act' to restore state) */ 92 93 /* Raise the signal, and unblock the signal to deliver it */ 94 if ((raise(sig) == -1) || 95 (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)) 96 goto restore_act; 97 98 /* Flag successful raise() */ 99 retval = 0; 100 101 /* Restore the original handler */ 102 restore_act: 103 oerrno = errno; 104 (void)sigaction(sig, &origact, NULL); 105 errno = oerrno; 106 107 /* Restore the original mask */ 108 restore_mask: 109 oerrno = errno; 110 (void)sigprocmask(SIG_SETMASK, &origmask, NULL); 111 errno = oerrno; 112 113 restore_none: 114 return retval; 115 } 116 117 #endif /* ! HAVE_RAISE_DEFAULT_SIGNAL */ 118