1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 * AUTHOR : Dave Baumgartner
4 * : Rewrote 12/92 by Richard Logan
5 * CO-PILOT : Barrie Kletscher
6 * DATE STARTED : 10/17/85
7 * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it would be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * Further, this software is distributed without any warranty that it is
18 * free of the rightful claim of any third person regarding infringement
19 * or the like. Any license provided herein, whether implied or
20 * otherwise, applies only to this software file. Patent licenses, if
21 * any, provided herein do not apply to combinations of this program with
22 * other software, or any other product whatsoever.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 *
28 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
29 * Mountain View, CA 94043, or:
30 *
31 * http://www.sgi.com
32 *
33 * For further information regarding this notice, see:
34 *
35 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
36 *
37 */
38 /*
39 * TEST ITEMS
40 *
41 * 1. SIGKILL can not be set to be caught, errno:EINVAL (POSIX).
42 * 2. SIGKILL can not be caught.
43 * 3. SIGKILL can not be set to be ignored, errno:EINVAL (POSIX).
44 * 4. SIGKILL can not be ignored.
45 * 5. SIGKILL can not be reset to default, errno:EINVAL (POSIX).
46 */
47 #include <signal.h>
48 #include <errno.h>
49 #include <unistd.h>
50 #include <fcntl.h>
51 #include <string.h>
52 #include <stdlib.h>
53 #include <sys/wait.h>
54
55 #include "test.h"
56 #include "safe_macros.h"
57
58 static void setup(void);
59 static void do_test(int tc);
60 static void do_child(void);
61 static void catchsig(int sig);
62
63 static struct tcase {
64 void (*sighandler)(int);
65 int kill;
66 } tcases[] = {
67 {SIG_IGN, 0},
68 {SIG_DFL, 0},
69 {catchsig, 0},
70 {SIG_IGN, 1},
71 {SIG_DFL, 1},
72 {catchsig, 1},
73 };
74
75 char *TCID = "signal01";
76 int TST_TOTAL = ARRAY_SIZE(tcases);
77
78 static int tcase;
79
main(int argc,char * argv[])80 int main(int argc, char *argv[])
81 {
82 int lc, i;
83
84 tst_parse_opts(argc, argv, NULL, NULL);
85
86 #ifdef UCLINUX
87 maybe_run_child(&do_child, "d", &tcase);
88 #endif
89
90 setup();
91
92 for (lc = 0; TEST_LOOPING(lc); lc++) {
93 for (i = 0; i < TST_TOTAL; i++)
94 do_test(i);
95 }
96
97 tst_exit();
98 }
99
do_test(int tc)100 static void do_test(int tc)
101 {
102 pid_t pid;
103 int res;
104 pid = FORK_OR_VFORK();
105
106 switch (pid) {
107 case 0:
108 #ifdef UCLINUX
109 if (self_exec(argv0, "d", tc) < 0)
110 tst_brkm(TBROK | TERRNO, NULL, "self_exec() failed");
111 #else
112 tcase = tc;
113 do_child();
114 #endif
115 break;
116 case -1:
117 tst_resm(TBROK | TERRNO, "fork() failed");
118 break;
119 default:
120 if (tcases[tc].kill) {
121 TST_PROCESS_STATE_WAIT(NULL, pid, 'S');
122
123 SAFE_KILL(NULL, pid, SIGKILL);
124
125 SAFE_WAITPID(NULL, pid, &res, 0);
126
127 if (WIFSIGNALED(res)) {
128 if (WTERMSIG(res) == SIGKILL) {
129 tst_resm(TPASS, "Child killed with SIGKILL");
130 } else {
131 tst_resm(TFAIL, "Child killed with %s",
132 tst_strsig(WTERMSIG(res)));
133 }
134 } else {
135 tst_resm(TFAIL, "Child not killed by signal");
136 }
137 } else {
138 tst_record_childstatus(NULL, pid);
139 }
140 break;
141 }
142 }
143
catchsig(int sig)144 static void catchsig(int sig)
145 {
146 (void)sig;
147 }
148
strhandler(void * sighandler)149 static const char *strhandler(void *sighandler)
150 {
151 switch ((long)sighandler) {
152 case (long)SIG_DFL:
153 return "SIG_DFL";
154 case (long)SIG_IGN:
155 return "SIG_IGN";
156 default:
157 return "catchsig()";
158 }
159 }
160
do_child(void)161 static void do_child(void)
162 {
163 void *ret;
164 void (*sighandler)(int) = tcases[tcase].sighandler;
165
166 ret = signal(SIGKILL, sighandler);
167
168 if (tcases[tcase].kill)
169 pause();
170
171 if (ret == SIG_ERR || errno == EINVAL) {
172 tst_resm(TPASS, "signal(SIGKILL, %p(%s)) failed with EINVAL",
173 sighandler, strhandler(sighandler));
174 } else {
175 if (ret != SIG_ERR) {
176 tst_resm(TFAIL, "signal(SIGKILL, %p(%s)) didn't fail",
177 sighandler, strhandler(sighandler));
178 } else {
179 tst_resm(TFAIL | TERRNO,
180 "signal(SIGKILL, %p(%s)) should fail with EINVAL",
181 sighandler, strhandler(sighandler));
182 }
183 }
184
185 tst_exit();
186 }
187
setup(void)188 static void setup(void)
189 {
190 tst_sig(FORK, DEF_HANDLER, NULL);
191
192 TEST_PAUSE;
193 }
194