1/*	$NetBSD$	*/
2
3/*++
4/* NAME
5/*	sigdelay 3
6/* SUMMARY
7/*	delay/resume signal delivery
8/* SYNOPSIS
9/*	#include <sigdelay.h>
10/*
11/*	void	sigdelay()
12/*
13/*	void	sigresume()
14/* DESCRIPTION
15/*	sigdelay() delays delivery of signals. Signals that
16/*	arrive in the mean time will be queued.
17/*
18/*	sigresume() resumes delivery of signals. Signals that have
19/*	arrived in the mean time will be delivered.
20/* DIAGNOSTICS
21/*	All errors are fatal.
22/* BUGS
23/*	The signal queue may be really short (as in: one per signal type).
24/*
25/*	Some signals such as SIGKILL cannot be blocked.
26/* LICENSE
27/* .ad
28/* .fi
29/*	The Secure Mailer license must be distributed with this software.
30/* AUTHOR(S)
31/*	Wietse Venema
32/*	IBM T.J. Watson Research
33/*	P.O. Box 704
34/*	Yorktown Heights, NY 10598, USA
35/*--*/
36
37/* System library. */
38
39#include <sys_defs.h>
40#include <signal.h>
41
42/* Utility library. */
43
44#include "msg.h"
45#include "posix_signals.h"
46#include "sigdelay.h"
47
48/* Application-specific. */
49
50static sigset_t saved_sigmask;
51static sigset_t block_sigmask;
52static int suspending;
53static int siginit_done;
54
55/* siginit - compute signal mask only once */
56
57static void siginit(void)
58{
59    int     sig;
60
61    siginit_done = 1;
62    sigemptyset(&block_sigmask);
63    for (sig = 1; sig < NSIG; sig++)
64	sigaddset(&block_sigmask, sig);
65}
66
67/* sigresume - deliver delayed signals and disable signal delay */
68
69void    sigresume(void)
70{
71    if (suspending != 0) {
72	suspending = 0;
73	if (sigprocmask(SIG_SETMASK, &saved_sigmask, (sigset_t *) 0) < 0)
74	    msg_fatal("sigresume: sigprocmask: %m");
75    }
76}
77
78/* sigdelay - save signal mask and block all signals */
79
80void    sigdelay(void)
81{
82    if (siginit_done == 0)
83	siginit();
84    if (suspending == 0) {
85	suspending = 1;
86	if (sigprocmask(SIG_BLOCK, &block_sigmask, &saved_sigmask) < 0)
87	    msg_fatal("sigdelay: sigprocmask: %m");
88    }
89}
90
91#ifdef TEST
92
93 /*
94  * Test program - press Ctrl-C twice while signal delivery is delayed, and
95  * see how many signals are delivered when signal delivery is resumed.
96  */
97
98#include <stdio.h>
99#include <unistd.h>
100#include <stdlib.h>
101
102static void gotsig(int sig)
103{
104    printf("Got signal %d\n", sig);
105}
106
107int     main(int unused_argc, char **unused_argv)
108{
109    signal(SIGINT, gotsig);
110    signal(SIGQUIT, gotsig);
111
112    printf("Delaying signal delivery\n");
113    sigdelay();
114    sleep(5);
115    printf("Resuming signal delivery\n");
116    sigresume();
117    exit(0);
118}
119
120#endif
121