1 /* IBM Corporation */
2 /* 01/02/2003	Port to LTP avenkat@us.ibm.com */
3 /* 06/30/2001	Port to Linux	nsharoff@us.ibm.com */
4 
5 /*
6  *
7  *   Copyright (c) International Business Machines  Corp., 2002
8  *
9  *   This program is free software;  you can redistribute it and/or modify
10  *   it under the terms of the GNU General Public License as published by
11  *   the Free Software Foundation; either version 2 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This program is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with this program;  if not, write to the Free Software
21  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 			   /*kill2.c */
25 /*======================================================================
26 >KEYS:  < kill(), wait(), signal()
27 >WHAT:  < Check that when a child is killed by its parent, it returns the
28    	< correct values to the waiting parent--the child sets signal to
29    	< ignore the kill
30 >HOW:   < For each signal: Send that signal to a child that has elected
31 	< to catch the signal, check that the correct status was returned
32 	< to the waiting parent.
33 	< NOTE: Signal 9 (kill) is not catchable, and must be dealt with
34 	< separately.
35 >BUGS:  < None known
36 ======================================================================*/
37 #ifndef _GNU_SOURCE
38 #define _GNU_SOURCE 1
39 #endif
40 
41 #include <stdio.h>
42 #include <sys/types.h>
43 #include <signal.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <sys/wait.h>
47 #include <errno.h>
48 
49 //char progname[] = "kill2()";
50 /*****  LTP Port        *****/
51 #include "test.h"
52 #define ITER    3
53 #define FAILED 0
54 #define PASSED 1
55 
56 char *TCID = "kill12";
57 
58 int local_flag = PASSED;
59 int block_number;
60 FILE *temp;
61 int TST_TOTAL = 1;
62 static int sig;
63 
64 int anyfail();
65 int blenter();
66 int instress();
67 void setup();
68 void terror();
69 void fail_exit();
70 void ok_exit();
71 int forkfail();
72 void do_child();
73 
74 /*****  **      **      *****/
75 
76 int chflag;
77 
78 /*--------------------------------------------------------------------*/
main(int argc,char ** argv)79 int main(int argc, char **argv)
80 {
81 /***** BEGINNING OF MAIN. *****/
82 	int pid, npid;
83 	int nsig, exno, nexno, status;
84 	int ret_val = 0;
85 	int core;
86 	void chsig();
87 
88 #ifdef UCLINUX
89 
90 	tst_parse_opts(argc, argv, NULL, NULL);
91 
92 	maybe_run_child(&do_child, "dd", &temp, &sig);
93 #endif
94 
95 	setup();
96 	//tempdir();            /* move to new directory */ 12/20/2003
97 	blenter();
98 
99 	exno = 1;
100 
101 	if (sigset(SIGCLD, chsig) == SIG_ERR) {
102 		fprintf(temp, "\tsigset failed, errno = %d\n", errno);
103 		fail_exit();
104 	}
105 
106 	for (sig = 1; sig < 14; sig++) {
107 		fflush(temp);
108 		chflag = 0;
109 
110 		pid = FORK_OR_VFORK();
111 		if (pid < 0) {
112 			forkfail();
113 		}
114 
115 		if (pid == 0) {
116 #ifdef UCLINUX
117 			if (self_exec(argv[0], "dd", temp, sig) < 0) {
118 				tst_brkm(TBROK, NULL, "self_exec FAILED - "
119 					 "terminating test.");
120 			}
121 #else
122 			do_child();
123 #endif
124 		} else {
125 			//fprintf(temp, "Testing signal %d\n", sig);
126 
127 			while (!chflag)	/* wait for child */
128 				sleep(1);
129 
130 			kill(pid, sig);	/* child should ignroe this sig */
131 			kill(pid, SIGCLD);	/* child should exit */
132 
133 #ifdef BCS
134 			while ((npid = wait(&status)) != pid
135 			       || (npid == -1 && errno == EINTR)) ;
136 			if (npid != pid) {
137 				fprintf(temp,
138 					"wait error: wait returned wrong pid\n");
139 				ret_val = 1;
140 			}
141 #else
142 			while ((npid = waitpid(pid, &status, 0)) != -1
143 			       || errno == EINTR) ;
144 #endif
145 
146 			/*
147 			   nsig = status & 0177;
148 			   core = status & 0200;
149 			   nexno = (status & 0xff00) >> 8;
150 			 */
151 			/*****  LTP Port        *****/
152 			nsig = WTERMSIG(status);
153 #ifdef WCOREDUMP
154 			core = WCOREDUMP(status);
155 #endif
156 			nexno = WIFEXITED(status);
157 			/*****  **      **      *****/
158 
159 			/* nsig is the signal number returned by wait
160 			   it should be 0, except when sig = 9          */
161 
162 			if ((sig == 9) && (nsig != sig)) {
163 				fprintf(temp, "wait error: unexpected signal"
164 					" returned when the signal sent was 9"
165 					" The status of the process is %d \n",
166 					status);
167 				ret_val = 1;
168 			}
169 			if ((sig != 9) && (nsig != 0)) {
170 				fprintf(temp, "wait error: unexpected signal "
171 					"returned, the status of the process is "
172 					"%d  \n", status);
173 				ret_val = 1;
174 			}
175 
176 			/* nexno is the exit number returned by wait
177 			   it should be 1, except when sig = 9          */
178 
179 			if (sig == 9)
180 				if (nexno != 0) {
181 					fprintf(temp, "signal error: unexpected"
182 						" exit number returned when"
183 						" signal sent was 9, the status"
184 						" of the process is %d \n",
185 						status);
186 					ret_val = 1;
187 				} else;
188 			else if (nexno != 1) {
189 				fprintf(temp, "signal error: unexpected exit "
190 					"number returned,the status of the"
191 					" process is %d\n", status);
192 				ret_val = 1;
193 			}
194 		}
195 	}
196 	if (ret_val)
197 		local_flag = FAILED;
198 
199 /*--------------------------------------------------------------------*/
200 	anyfail();
201 	tst_exit();
202 }					/******** END OF MAIN. ********/
203 
204 /*--------------------------------------------------------------------*/
205 
chsig(void)206 void chsig(void)
207 {
208 	chflag++;
209 }
210 
211 /****** LTP Port        *****/
anyfail(void)212 int anyfail(void)
213 {
214 	(local_flag == FAILED) ? tst_resm(TFAIL,
215 					  "Test failed") : tst_resm(TPASS,
216 								    "Test passed");
217 	tst_exit();
218 }
219 
do_child(void)220 void do_child(void)
221 {
222 	int exno = 1;
223 
224 #ifdef UCLINUX
225 	if (sigset(SIGCLD, chsig) == SIG_ERR) {
226 		fprintf(temp, "\tsigset failed, errno = %d\n", errno);
227 		fail_exit();
228 	}
229 #endif
230 
231 	sigset(sig, SIG_IGN);	/* set to ignore signal */
232 	kill(getppid(), SIGCLD);	/* tell parent we are ready */
233 	while (!chflag)
234 		sleep(1);	/* wait for parent */
235 
236 	exit(exno);
237 }
238 
setup(void)239 void setup(void)
240 {
241 	temp = stderr;
242 }
243 
blenter(void)244 int blenter(void)
245 {
246 	//tst_resm(TINFO, "Enter block %d", block_number);
247 	local_flag = PASSED;
248 	return 0;
249 }
250 
terror(char * message)251 void terror(char *message)
252 {
253 	tst_resm(TBROK, "Reason: %s:%s", message, strerror(errno));
254 }
255 
fail_exit(void)256 void fail_exit(void)
257 {
258 	local_flag = FAILED;
259 	anyfail();
260 
261 }
262 
forkfail(void)263 int forkfail(void)
264 {
265 	tst_brkm(TBROK, NULL, "FORK FAILED - terminating test.");
266 }
267 
268 /****** ** **   *******/
269