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