xref: /netbsd-src/lib/libc/gen/sigset.c (revision ce099b40997c43048fb78bd578195f81d2456523)
1*ce099b40Smartin /*	$NetBSD: sigset.c,v 1.2 2008/04/28 20:22:59 martin Exp $	*/
230a90a73Skleink 
330a90a73Skleink /*-
430a90a73Skleink  * Copyright (c) 2003 The NetBSD Foundation, Inc.
530a90a73Skleink  * All rights reserved.
630a90a73Skleink  *
730a90a73Skleink  * This code is derived from software contributed to The NetBSD Foundation
830a90a73Skleink  * by Klaus Klein.
930a90a73Skleink  *
1030a90a73Skleink  * Redistribution and use in source and binary forms, with or without
1130a90a73Skleink  * modification, are permitted provided that the following conditions
1230a90a73Skleink  * are met:
1330a90a73Skleink  * 1. Redistributions of source code must retain the above copyright
1430a90a73Skleink  *    notice, this list of conditions and the following disclaimer.
1530a90a73Skleink  * 2. Redistributions in binary form must reproduce the above copyright
1630a90a73Skleink  *    notice, this list of conditions and the following disclaimer in the
1730a90a73Skleink  *    documentation and/or other materials provided with the distribution.
1830a90a73Skleink  *
1930a90a73Skleink  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2030a90a73Skleink  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2130a90a73Skleink  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2230a90a73Skleink  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2330a90a73Skleink  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2430a90a73Skleink  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2530a90a73Skleink  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2630a90a73Skleink  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2730a90a73Skleink  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2830a90a73Skleink  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2930a90a73Skleink  * POSSIBILITY OF SUCH DAMAGE.
3030a90a73Skleink  */
3130a90a73Skleink 
3230a90a73Skleink #include <sys/cdefs.h>
3330a90a73Skleink #if defined(LIBC_SCCS) && !defined(lint)
34*ce099b40Smartin __RCSID("$NetBSD: sigset.c,v 1.2 2008/04/28 20:22:59 martin Exp $");
3530a90a73Skleink #endif
3630a90a73Skleink 
3730a90a73Skleink #include "namespace.h"
3830a90a73Skleink #include <errno.h>
3930a90a73Skleink #include <signal.h>
4030a90a73Skleink #include <stddef.h>
4130a90a73Skleink 
4230a90a73Skleink sig_t
sigset(int sig,void (* disp)(int))4330a90a73Skleink sigset(int sig, void (*disp)(int))
4430a90a73Skleink {
4530a90a73Skleink 	sigset_t set, oset;
4630a90a73Skleink 	struct sigaction sa, osa;
4730a90a73Skleink 
4830a90a73Skleink 	osa.sa_handler = SIG_ERR;
4930a90a73Skleink 
5030a90a73Skleink 	if (disp == SIG_HOLD) {
5130a90a73Skleink 		/* Add sig to current signal mask. */
5230a90a73Skleink 		if (sigemptyset(&set) != 0)
5330a90a73Skleink 			goto out;
5430a90a73Skleink 		if (sigaddset(&set, sig) != 0)
5530a90a73Skleink 			goto out;
5630a90a73Skleink 		if (sigprocmask(SIG_BLOCK, &set, &oset) != 0)
5730a90a73Skleink 			goto out;
5830a90a73Skleink 
5930a90a73Skleink 		if (sigismember(&oset, sig)) {
6030a90a73Skleink 			/* Had been masked before, return SIG_HOLD. */
6130a90a73Skleink 			osa.sa_handler = SIG_HOLD;
6230a90a73Skleink 		} else {
6330a90a73Skleink 			/* Return previous disposition. */
6430a90a73Skleink 		 	(void)sigaction(sig, NULL, &osa);
6530a90a73Skleink 		}
6630a90a73Skleink 	} else if (disp == SIG_ERR) {
6730a90a73Skleink 		errno = EINVAL;
6830a90a73Skleink 	} else {
6930a90a73Skleink 		/* Set up and install new disposition. */
7030a90a73Skleink 		sa.sa_handler = disp;
7130a90a73Skleink 		if (sigemptyset(&sa.sa_mask) != 0)
7230a90a73Skleink 			goto out;
7330a90a73Skleink 		sa.sa_flags = 0;
7430a90a73Skleink 
7530a90a73Skleink 		if (sigaction(sig, &sa, &osa) != 0) {
7630a90a73Skleink 			osa.sa_handler = SIG_ERR;
7730a90a73Skleink 			goto out;
7830a90a73Skleink 		}
7930a90a73Skleink 
8030a90a73Skleink 		/* Delete sig from current signal mask. */
8130a90a73Skleink 		if (sigemptyset(&set) != 0)
8230a90a73Skleink 			return (SIG_ERR);
8330a90a73Skleink 		if (sigaddset(&set, sig) != 0)
8430a90a73Skleink 			return (SIG_ERR);
8530a90a73Skleink 		if (sigprocmask(SIG_UNBLOCK, &set, &oset) != 0)
8630a90a73Skleink 			return (SIG_ERR);
8730a90a73Skleink 
8830a90a73Skleink 		/* If had been masked before, return SIG_HOLD. */
8930a90a73Skleink 		if (sigismember(&oset, sig))
9030a90a73Skleink 			osa.sa_handler = SIG_HOLD;
9130a90a73Skleink 	}
9230a90a73Skleink 
9330a90a73Skleink  out:
9430a90a73Skleink 	return (osa.sa_handler);
9530a90a73Skleink }
96