main netmisc / compat / raise_default_signal.c
  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#include <sys/cdefs.h>
 33#if defined(LIBC_SCCS) && !defined(lint)
 34__RCSID("$NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $");
 35#endif
 36
 37#include "netcompat.h"
 38#include <errno.h>
 39#include <signal.h>
 40#include <stdio.h>
 41#include <string.h>
 42
 43/*
 44 * raise_default_signal sig
 45 *	Raise the default signal handler for sig, by
 46 *	- block all signals
 47 *	- set the signal handler to SIG_DFL
 48 *	- raise the signal
 49 *	- unblock the signal to deliver it
 50 *
 51 *	The original signal mask and signal handler is restored on exit
 52 *	(whether successful or not).
 53 *
 54 *	Returns 0 on success, or -1 on failure with errno set to
 55 *	on of the values for sigemptyset(), sigaddset(), sigprocmask(),
 56 *	sigaction(), or raise().
 57 */
 58int
 59raise_default_signal(int sig)
 60{
 61	struct sigaction origact, act;
 62	sigset_t origmask, fullmask, mask;
 63	int retval, oerrno;
 64
 65	retval = -1;
 66
 67		/* Setup data structures */
 68		/* XXX memset(3) isn't async-safe according to signal(7) */
 69	(void)memset(&act, 0, sizeof(act));
 70	act.sa_handler = SIG_DFL;
 71	act.sa_flags = 0;
 72	if ((sigemptyset(&act.sa_mask) == -1) ||
 73	    (sigfillset(&fullmask) == -1) ||
 74	    (sigemptyset(&mask) == -1) ||
 75	    (sigaddset(&mask, sig) == -1))
 76		goto restore_none;
 77
 78		/* Block all signals */
 79	if (sigprocmask(SIG_BLOCK, &fullmask, &origmask) == -1)
 80		goto restore_none;
 81		/* (use 'goto restore_mask' to restore state) */
 82
 83		/* Enable the SIG_DFL handler */
 84	if (sigaction(sig, &act, &origact) == -1)
 85		goto restore_mask;
 86		/* (use 'goto restore_act' to restore state) */
 87
 88		/* Raise the signal, and unblock the signal to deliver it */
 89	if ((raise(sig) == -1) ||
 90	    (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1))
 91		goto restore_act;
 92
 93		/* Flag successful raise() */
 94	retval = 0;
 95
 96		/* Restore the original handler */
 97 restore_act:
 98	oerrno = errno;
 99	(void)sigaction(sig, &origact, NULL);
100	errno = oerrno;
101
102		/* Restore the original mask */
103 restore_mask:
104	oerrno = errno;
105	(void)sigprocmask(SIG_SETMASK, &origmask, NULL);
106	errno = oerrno;
107
108restore_none:
109	return retval;
110}