1#include <unistd.h>
2#include <signal.h>
3#include <errno.h>
4#include <string.h>
5#include <stdio.h>
6#include <sys/wait.h>
7#include <sys/types.h>
8#include <stdlib.h>
9
10static void do_exec(const char *path, const char *arg, const sigset_t *mask)
11{
12	pid_t pid;
13	int status;
14
15	pid = fork();
16	if (pid == -1) {
17		perror("fork");
18		exit(1);
19	}
20	if (pid == 0) {
21		sigprocmask(SIG_SETMASK, mask, NULL);
22		execl(path, path, arg, NULL);
23
24		fprintf(stderr, "FAILED: execl failed with %s\n",
25			strerror(errno));
26	} else {
27		int ret;
28		do
29			ret = waitpid(pid, &status, 0);
30		while(ret == -1 && errno == EINTR);
31		if (ret != pid) {
32			perror("waitpid");
33			exit(1);
34		}
35		if (status != 0) {
36			fprintf(stderr, "child exec failed\n");
37			exit(1);
38		}
39	}
40}
41
42int main(int argc, char **argv)
43{
44	if (argc == 1) {
45		sigset_t mask;
46
47		sigfillset(&mask);
48		do_exec(argv[0], "full", &mask);
49
50		sigemptyset(&mask);
51		do_exec(argv[0], "empty", &mask);
52	} else {
53		sigset_t mask;
54		int i;
55		int empty;
56
57		if (strcmp(argv[1], "full") == 0)
58			empty = 0;
59		else if (strcmp(argv[1], "empty") == 0)
60			empty = 1;
61		else {
62			fprintf(stderr, "empty or full?\n");
63			exit(1);
64		}
65
66		sigprocmask(SIG_SETMASK, NULL, &mask);
67
68		for(i = 1; i < NSIG; i++) {
69			if (i == SIGKILL || i == SIGSTOP)
70				continue;
71
72			if (empty) {
73				if (sigismember(&mask, i))
74					printf("empty: signal %d added to mask\n", i);
75			} else {
76				if (!sigismember(&mask, i))
77					printf("full: signal %d missing from mask\n", i);
78			}
79		}
80	}
81
82	return 0;
83}
84