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 58static void setup(void); 59static void do_test(int tc); 60static void do_child(void); 61static void catchsig(int sig); 62 63static 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 75char *TCID = "signal01"; 76int TST_TOTAL = ARRAY_SIZE(tcases); 77 78static int tcase; 79 80int 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 100static 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 144static void catchsig(int sig) 145{ 146 (void)sig; 147} 148 149static 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 161static 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 188static void setup(void) 189{ 190 tst_sig(FORK, DEF_HANDLER, NULL); 191 192 TEST_PAUSE; 193} 194