1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it
5f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as
6f08c3bdfSopenharmony_ci * published by the Free Software Foundation.
7f08c3bdfSopenharmony_ci *
8f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but
9f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
10f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * Further, this software is distributed without any warranty that it is
13f08c3bdfSopenharmony_ci * free of the rightful claim of any third person regarding infringement
14f08c3bdfSopenharmony_ci * or the like.  Any license provided herein, whether implied or
15f08c3bdfSopenharmony_ci * otherwise, applies only to this software file.  Patent licenses, if
16f08c3bdfSopenharmony_ci * any, provided herein do not apply to combinations of this program with
17f08c3bdfSopenharmony_ci * other software, or any other product whatsoever.
18f08c3bdfSopenharmony_ci *
19f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License along
20f08c3bdfSopenharmony_ci * with this program; if not, write the Free Software Foundation, Inc.,
21f08c3bdfSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22f08c3bdfSopenharmony_ci *
23f08c3bdfSopenharmony_ci * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24f08c3bdfSopenharmony_ci * Mountain View, CA  94043, or:
25f08c3bdfSopenharmony_ci *
26f08c3bdfSopenharmony_ci * http://www.sgi.com
27f08c3bdfSopenharmony_ci *
28f08c3bdfSopenharmony_ci * For further information regarding this notice, see:
29f08c3bdfSopenharmony_ci *
30f08c3bdfSopenharmony_ci * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31f08c3bdfSopenharmony_ci *
32f08c3bdfSopenharmony_ci */
33f08c3bdfSopenharmony_ci/* $Id: kill02.c,v 1.10 2009/08/28 13:20:15 vapier Exp $ */
34f08c3bdfSopenharmony_ci/***********************************************************************************
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci    OS Test -  Silicon Graphics, Inc.
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci    TEST IDENTIFIER :  kill02  Sending a signal to processes with the same process group ID.
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci    PARENT DOCUMENT :  kiltds01  Kill System Call.
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_ci    AUTHOR          :  Dave Baumgartner
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_ci    CO-PILOT        :  Barrie Kletscher
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_ci    DATE STARTED    :  12/30/85
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_ci    TEST ITEMS
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci	1. Sending a signal to pid of zero sends to all processes whose process
51f08c3bdfSopenharmony_ci	   group ID is equal to the process group ID as the sender.
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_ci	2. Sending a signal to pid of zero does not send to processes in another process group.
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci    OUTPUT SPECIFICATIONS
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ci	PASS :
58f08c3bdfSopenharmony_ci		kiltcs02 1 PASS The signal was sent to all processes in the process group.
59f08c3bdfSopenharmony_ci		kiltcs02 2 PASS The signal was not sent to selective processes that were not in the process group.
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_ci	FAIL :
62f08c3bdfSopenharmony_ci		kiltcs02 1 FAIL The signal was not sent to all processes in the process group.
63f08c3bdfSopenharmony_ci		kiltcs02 2 FAIL The signal was sent to a process that was not in the process group.
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ci	BROK :
66f08c3bdfSopenharmony_ci		kiltcs02 # BROK System call XXX failed. Errno:X, Error message:XXX.
67f08c3bdfSopenharmony_ci		kiltcs02 # BROK Setting to catch unexpected signal %d failed. Errno: %d, Error message %s.
68f08c3bdfSopenharmony_ci		kiltcs02 # BROK Setting to ignore signal %d failed. Errno: %d, Error message %s.
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_ci	WARN :
71f08c3bdfSopenharmony_ci		kiltcs02 0 WARN Unexpected signal X was caught.
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci    SPECIAL PROCEDURAL REQUIREMENTS
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci	The program must be linked with tst_res.o.
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci    DETAILED DESCRIPTION
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci	**Setup**
80f08c3bdfSopenharmony_ci	Set up unexpected signal handling.
81f08c3bdfSopenharmony_ci	Set up one pipe for each process to be created with no blocking for read.
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_ci	**MAIN**
84f08c3bdfSopenharmony_ci	If setup fails exit.
85f08c3bdfSopenharmony_ci	Fork 2 children(1 & 2).
86f08c3bdfSopenharmony_ci	Wait for set up complete messages from the 1st and 2nd child.
87f08c3bdfSopenharmony_ci	Send the signal SIGUSR1 with pid equal to zero.
88f08c3bdfSopenharmony_ci	Sleep a reasonable amount of time so that each child has been swapped in
89f08c3bdfSopenharmony_ci	to process the signal.
90f08c3bdfSopenharmony_ci	Now decide the outcome of the test items by reading from each pipe to find
91f08c3bdfSopenharmony_ci	out if the child was interrupted by the signal and wrote to it.
92f08c3bdfSopenharmony_ci	Remove the second child.
93f08c3bdfSopenharmony_ci	Tell the first child it is time to remove it's child B because the decisions have been made.
94f08c3bdfSopenharmony_ci	Exit.
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci	**First Child**
97f08c3bdfSopenharmony_ci	Set to catch SIGUSR1 with an int_rout1.
98f08c3bdfSopenharmony_ci	Set up to handle the message from the parent to remove child B.
99f08c3bdfSopenharmony_ci	Fork two children(A & B).
100f08c3bdfSopenharmony_ci	Wait for set up complete messages from child A & child B.
101f08c3bdfSopenharmony_ci	Send a set up complete message to the parent.
102f08c3bdfSopenharmony_ci	Pause until the signal SIGUSR1 comes in from the parent.
103f08c3bdfSopenharmony_ci	Pause until the parent says it is time to remove the child.
104f08c3bdfSopenharmony_ci	Exit.
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_ci	**Second Child**
107f08c3bdfSopenharmony_ci	Set to catch SIGUSR1 with an int_rout2.
108f08c3bdfSopenharmony_ci	Set the process group to be something different than the parents.
109f08c3bdfSopenharmony_ci	Send a set up complete message to the parent.
110f08c3bdfSopenharmony_ci	Pause until killed by parent because this child shouldn't receive signal SIGUSR1.
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ci	**Child A**
113f08c3bdfSopenharmony_ci	Set to catch SIGUSR1 with an int_routA.
114f08c3bdfSopenharmony_ci	Send a set up complete message to the parent(First Child).
115f08c3bdfSopenharmony_ci	Pause until the signal SIGUSR1 comes in from the parent.
116f08c3bdfSopenharmony_ci	Exit.
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci	**Child B**
119f08c3bdfSopenharmony_ci	Set to catch SIGUSR1 with an int_routB.
120f08c3bdfSopenharmony_ci	Set the process group to be something different than the parents(First Child's).
121f08c3bdfSopenharmony_ci	Send a set up complete message to the parent.
122f08c3bdfSopenharmony_ci	Pause until killed by parent because this child shouldn't receive signal SIGUSR1.
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_ci	**usr1_rout-Used by all children**
125f08c3bdfSopenharmony_ci	Write to the appropriate pipe that the signal SIGUSR1 was caught.
126f08c3bdfSopenharmony_ci
127f08c3bdfSopenharmony_ci	**usr2_rout**
128f08c3bdfSopenharmony_ci	Remove child B.
129f08c3bdfSopenharmony_ci
130f08c3bdfSopenharmony_ci******************************************************************************/
131f08c3bdfSopenharmony_ci#include <sys/param.h>
132f08c3bdfSopenharmony_ci#include <sys/wait.h>
133f08c3bdfSopenharmony_ci#include <errno.h>
134f08c3bdfSopenharmony_ci#include <fcntl.h>
135f08c3bdfSopenharmony_ci#include <signal.h>
136f08c3bdfSopenharmony_ci#include <string.h>
137f08c3bdfSopenharmony_ci#include <stdlib.h>
138f08c3bdfSopenharmony_ci#include "test.h"
139f08c3bdfSopenharmony_ci
140f08c3bdfSopenharmony_ci#define CHAR_SET_FAILED	"0"	/*Set up failing status transferred through the pipe.   */
141f08c3bdfSopenharmony_ci#define CHAR_SET_PASSED	"1"	/*Set up passing status transferred through the pipe.   */
142f08c3bdfSopenharmony_ci#define SIG_CAUGHT	"2"	/*Indicates that the signal SIGUSR1 was caught.         */
143f08c3bdfSopenharmony_ci#define SIG_RECEIVED	1	/*Integer value that indicates that the signal SIGUSR1  */
144f08c3bdfSopenharmony_ci				/*was caught.                                           */
145f08c3bdfSopenharmony_ci#define SIG_NOT_RECD	0	/*Integer value that indicates that the signal SIGUSR1  */
146f08c3bdfSopenharmony_ci				/*was caught.                                           */
147f08c3bdfSopenharmony_ci#define INT_SET_FAILED	0	/*Set up failing status transferred through the pipe.   */
148f08c3bdfSopenharmony_ci#define INT_SET_PASSED	1	/*Set up passing status transferred through the pipe.   */
149f08c3bdfSopenharmony_ci#define SLEEP_TIME	10	/*Amount of time the children get to catch the signal   */
150f08c3bdfSopenharmony_ci#define TRUE	 	40	/*Child exits with this if execution was as     */
151f08c3bdfSopenharmony_ci				/*expected.                                             */
152f08c3bdfSopenharmony_ci#define FALSE	 	50	/*Child exits with this if it timed out waiting for the         */
153f08c3bdfSopenharmony_ci				/*parents signal.                                       */
154f08c3bdfSopenharmony_ci#define TIMEOUT		60	/*Amount of time given in alarm calls.                  */
155f08c3bdfSopenharmony_ci#define CHILD_EXIT(VAR) ((VAR >> 8) & 0377)	/*Exit value from the child.               */
156f08c3bdfSopenharmony_ci#define CHILD_SIG(VAR) (VAR & 0377)	/*Signal value from the termination of child.       */
157f08c3bdfSopenharmony_ci				/*from the parent.                                      */
158f08c3bdfSopenharmony_ci
159f08c3bdfSopenharmony_ciint pid1;			/*Return value from 1st fork. Global so that it can be  */
160f08c3bdfSopenharmony_ci				/*used in interrupt handling routines.                  */
161f08c3bdfSopenharmony_ciint pid2;			/*Return value from 2nd fork. Global so that it can be  */
162f08c3bdfSopenharmony_ci				/*used in interrupt handling routines.                  */
163f08c3bdfSopenharmony_ciint pidA;			/*Return value from 1st fork in child 1. Global so that it      */
164f08c3bdfSopenharmony_ci				/*can be used in interrupt handling routines.           */
165f08c3bdfSopenharmony_ciint pidB;			/*Return value from 2nd fork in child 1. Global so that it      */
166f08c3bdfSopenharmony_ci				/*can be used in interrupt handling routines.           */
167f08c3bdfSopenharmony_ciint pipe1_fd[2];		/*Pipe file descriptors used for communication          */
168f08c3bdfSopenharmony_ci				/*between child 1 and the 1st parent.                   */
169f08c3bdfSopenharmony_ciint pipe2_fd[2];		/*Pipe file descriptors used for communication          */
170f08c3bdfSopenharmony_ci				/*between child 2 and the 1st parent.                   */
171f08c3bdfSopenharmony_ciint pipeA_fd[2];		/*Pipe file descriptors used for communication          */
172f08c3bdfSopenharmony_ci				/*between child A and the 1st parent.                   */
173f08c3bdfSopenharmony_ciint pipeB_fd[2];		/*Pipe file descriptors used for communication          */
174f08c3bdfSopenharmony_ci				/*between child B and the 1st parent.                   */
175f08c3bdfSopenharmony_cichar pipe_buf[10];		/*Pipe buffer.                                          */
176f08c3bdfSopenharmony_cichar buf_tmp1[2], buf_tmp2[2];	/*Temp hold for info read into pipe_buf.                */
177f08c3bdfSopenharmony_ciint read1_stat = 0;		/*Number of characters read from pipe 1.                */
178f08c3bdfSopenharmony_ciint read2_stat = 0;		/*Number of characters read from pipe 2.                */
179f08c3bdfSopenharmony_ciint readA_stat = 0;		/*Number of characters read from pipe A.                */
180f08c3bdfSopenharmony_ciint readB_stat = 0;		/*Number of characters read from pipe B.                */
181f08c3bdfSopenharmony_ciint alarm_flag = FALSE;		/*This flag indicates an alarm time out.                        */
182f08c3bdfSopenharmony_cichar who_am_i = '0';		/*This indicates which process is which when using      */
183f08c3bdfSopenharmony_ci				/*interrupt routine usr1_rout.                          */
184f08c3bdfSopenharmony_ci
185f08c3bdfSopenharmony_civoid notify_timeout();		/*Signal handler that the parent enters if it times out */
186f08c3bdfSopenharmony_ci				/*waiting for the child to indicate its set up status.  */
187f08c3bdfSopenharmony_civoid parent_rout();		/*This is the parents routine.                          */
188f08c3bdfSopenharmony_civoid child1_rout();		/*This is child 1's routine.                            */
189f08c3bdfSopenharmony_civoid child2_rout();		/*This is child 2's routine.                            */
190f08c3bdfSopenharmony_civoid childA_rout();		/*This is child A's routine.                            */
191f08c3bdfSopenharmony_civoid childB_rout();		/*This is child B's routine.                            */
192f08c3bdfSopenharmony_civoid usr1_rout();		/*This routine is used by all children to indicate that */
193f08c3bdfSopenharmony_ci				/*they have caught signal SIGUSR1.                      */
194f08c3bdfSopenharmony_civoid par_kill();		/*This routine is called by the original parent to      */
195f08c3bdfSopenharmony_ci				/*remove child 2 and to indicate to child 1 to          */
196f08c3bdfSopenharmony_ci				/*remove its children.                                  */
197f08c3bdfSopenharmony_civoid chld1_kill();		/*This routine is used by child 1 to remove itself and  */
198f08c3bdfSopenharmony_ci				/*its children A and B.                                 */
199f08c3bdfSopenharmony_ci
200f08c3bdfSopenharmony_civoid setup();
201f08c3bdfSopenharmony_civoid cleanup();
202f08c3bdfSopenharmony_ci
203f08c3bdfSopenharmony_cichar *TCID = "kill02";
204f08c3bdfSopenharmony_ciint TST_TOTAL = 2;
205f08c3bdfSopenharmony_ci
206f08c3bdfSopenharmony_ci#ifdef UCLINUX
207f08c3bdfSopenharmony_cistatic char *argv0;
208f08c3bdfSopenharmony_civoid childA_rout_uclinux();
209f08c3bdfSopenharmony_civoid childB_rout_uclinux();
210f08c3bdfSopenharmony_ci#endif
211f08c3bdfSopenharmony_ci
212f08c3bdfSopenharmony_ciint main(int ac, char **av)
213f08c3bdfSopenharmony_ci{
214f08c3bdfSopenharmony_ci	int lc;
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci	tst_parse_opts(ac, av, NULL, NULL);
217f08c3bdfSopenharmony_ci
218f08c3bdfSopenharmony_ci#ifdef UCLINUX
219f08c3bdfSopenharmony_ci	argv0 = av[0];
220f08c3bdfSopenharmony_ci
221f08c3bdfSopenharmony_ci	maybe_run_child(&childA_rout_uclinux, "nd", 1, &pipeA_fd[1]);
222f08c3bdfSopenharmony_ci	maybe_run_child(&childB_rout_uclinux, "nd", 2, &pipeB_fd[1]);
223f08c3bdfSopenharmony_ci	maybe_run_child(&child1_rout, "ndddddd", 3, &pipe1_fd[1], &pipe2_fd[1],
224f08c3bdfSopenharmony_ci			&pipeA_fd[0], &pipeA_fd[1], &pipeB_fd[0], &pipeB_fd[1]);
225f08c3bdfSopenharmony_ci	maybe_run_child(&child2_rout, "nd", 4, &pipe2_fd[1]);
226f08c3bdfSopenharmony_ci#endif
227f08c3bdfSopenharmony_ci
228f08c3bdfSopenharmony_ci	setup();
229f08c3bdfSopenharmony_ci
230f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); lc++) {
231f08c3bdfSopenharmony_ci
232f08c3bdfSopenharmony_ci		tst_count = 0;
233f08c3bdfSopenharmony_ci
234f08c3bdfSopenharmony_ci		if ((pid1 = FORK_OR_VFORK()) > 0) {
235f08c3bdfSopenharmony_ci			if ((pid2 = FORK_OR_VFORK()) > 0) {
236f08c3bdfSopenharmony_ci				(void)parent_rout();
237f08c3bdfSopenharmony_ci			} else if (pid2 == 0) {
238f08c3bdfSopenharmony_ci#ifdef UCLINUX
239f08c3bdfSopenharmony_ci				if (self_exec(argv0, "nd", 4, pipe2_fd[1]) < 0) {
240f08c3bdfSopenharmony_ci					if (kill(pid1, SIGKILL) == -1
241f08c3bdfSopenharmony_ci					    && errno != ESRCH) {
242f08c3bdfSopenharmony_ci						tst_resm(TWARN,
243f08c3bdfSopenharmony_ci							 "Child process may not have been killed.");
244f08c3bdfSopenharmony_ci					}
245f08c3bdfSopenharmony_ci					tst_brkm(TBROK | TERRNO, cleanup,
246f08c3bdfSopenharmony_ci						 "fork failed");
247f08c3bdfSopenharmony_ci				}
248f08c3bdfSopenharmony_ci#else
249f08c3bdfSopenharmony_ci				(void)child2_rout();
250f08c3bdfSopenharmony_ci#endif
251f08c3bdfSopenharmony_ci			} else {
252f08c3bdfSopenharmony_ci				/*
253f08c3bdfSopenharmony_ci				 *  The second fork failed kill the first child.
254f08c3bdfSopenharmony_ci				 */
255f08c3bdfSopenharmony_ci				if (kill(pid1, SIGKILL) == -1 && errno != ESRCH) {
256f08c3bdfSopenharmony_ci					tst_resm(TWARN,
257f08c3bdfSopenharmony_ci						 "Child process may not have been killed.");
258f08c3bdfSopenharmony_ci				}
259f08c3bdfSopenharmony_ci				tst_brkm(TBROK | TERRNO, cleanup,
260f08c3bdfSopenharmony_ci					 "fork failed");
261f08c3bdfSopenharmony_ci			}
262f08c3bdfSopenharmony_ci
263f08c3bdfSopenharmony_ci		} else if (pid1 == 0) {
264f08c3bdfSopenharmony_ci			/*
265f08c3bdfSopenharmony_ci			 *  This is child 1.
266f08c3bdfSopenharmony_ci			 */
267f08c3bdfSopenharmony_ci#ifdef UCLINUX
268f08c3bdfSopenharmony_ci			if (self_exec
269f08c3bdfSopenharmony_ci			    (argv0, "ndddddd", 3, pipe1_fd[1], pipe2_fd[1],
270f08c3bdfSopenharmony_ci			     pipeA_fd[0], pipeA_fd[1], pipeB_fd[0],
271f08c3bdfSopenharmony_ci			     pipeB_fd[1]) < 0) {
272f08c3bdfSopenharmony_ci				tst_brkm(TBROK | TERRNO, cleanup,
273f08c3bdfSopenharmony_ci					 "self_exec() failed");
274f08c3bdfSopenharmony_ci			}
275f08c3bdfSopenharmony_ci#else
276f08c3bdfSopenharmony_ci			(void)child1_rout();
277f08c3bdfSopenharmony_ci#endif
278f08c3bdfSopenharmony_ci		} else {
279f08c3bdfSopenharmony_ci			/*
280f08c3bdfSopenharmony_ci			 * Fork failed.
281f08c3bdfSopenharmony_ci			 */
282f08c3bdfSopenharmony_ci			tst_brkm(TBROK | TERRNO, cleanup, "fork failed");
283f08c3bdfSopenharmony_ci		}
284f08c3bdfSopenharmony_ci	}
285f08c3bdfSopenharmony_ci
286f08c3bdfSopenharmony_ci	cleanup();
287f08c3bdfSopenharmony_ci	tst_exit();
288f08c3bdfSopenharmony_ci}				/* END OF MAIN. */
289f08c3bdfSopenharmony_ci
290f08c3bdfSopenharmony_ci/******************************************************************************
291f08c3bdfSopenharmony_ci *  This is the parents routine.  The parent waits for the children 1 and 2 to
292f08c3bdfSopenharmony_ci *  get set up. Then sends the signal and checks the outcome.
293f08c3bdfSopenharmony_ci *********************************************************************************/
294f08c3bdfSopenharmony_civoid parent_rout(void)
295f08c3bdfSopenharmony_ci{
296f08c3bdfSopenharmony_ci	/*
297f08c3bdfSopenharmony_ci	 *  Set to catch the alarm signal SIGALRM.
298f08c3bdfSopenharmony_ci	 */
299f08c3bdfSopenharmony_ci	if (signal(SIGALRM, notify_timeout) == SIG_ERR) {
300f08c3bdfSopenharmony_ci		(void)par_kill();
301f08c3bdfSopenharmony_ci		tst_brkm(TBROK, NULL,
302f08c3bdfSopenharmony_ci			 "Could not set to catch the parents time out alarm.");
303f08c3bdfSopenharmony_ci	}
304f08c3bdfSopenharmony_ci
305f08c3bdfSopenharmony_ci	/*
306f08c3bdfSopenharmony_ci	 *  Setting to catch the timeout alarm worked now let the children start up.
307f08c3bdfSopenharmony_ci	 *  Set an alarm which causes a time out on the read pipe loop.
308f08c3bdfSopenharmony_ci	 *  The children will notify the parent that set up is complete
309f08c3bdfSopenharmony_ci	 *  and the pass/fail status of set up.
310f08c3bdfSopenharmony_ci	 */
311f08c3bdfSopenharmony_ci	(void)alarm(TIMEOUT);
312f08c3bdfSopenharmony_ci
313f08c3bdfSopenharmony_ci	while ((read(pipe1_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
314f08c3bdfSopenharmony_ci		/*EMPTY*/;
315f08c3bdfSopenharmony_ci	strncpy(buf_tmp1, pipe_buf, 1);
316f08c3bdfSopenharmony_ci	(void)alarm(TIMEOUT);
317f08c3bdfSopenharmony_ci
318f08c3bdfSopenharmony_ci	while ((read(pipe2_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
319f08c3bdfSopenharmony_ci		/*EMPTY*/;
320f08c3bdfSopenharmony_ci	(void)alarm(0);		/*Reset the alarm clock. */
321f08c3bdfSopenharmony_ci	strncpy(buf_tmp2, pipe_buf, 1);
322f08c3bdfSopenharmony_ci
323f08c3bdfSopenharmony_ci	/*
324f08c3bdfSopenharmony_ci	 *  Check the alarm flag.
325f08c3bdfSopenharmony_ci	 */
326f08c3bdfSopenharmony_ci	if (alarm_flag == TRUE) {
327f08c3bdfSopenharmony_ci		tst_brkm(TBROK, NULL,
328f08c3bdfSopenharmony_ci			 "The set up of the children failed by timing out.");
329f08c3bdfSopenharmony_ci		(void)par_kill();
330f08c3bdfSopenharmony_ci		cleanup();
331f08c3bdfSopenharmony_ci	}
332f08c3bdfSopenharmony_ci
333f08c3bdfSopenharmony_ci	/*
334f08c3bdfSopenharmony_ci	 *  Check to see if either child failed in the set up.
335f08c3bdfSopenharmony_ci	 */
336f08c3bdfSopenharmony_ci	if ((strncmp(buf_tmp1, CHAR_SET_FAILED, 1) == 0) ||
337f08c3bdfSopenharmony_ci	    (strncmp(buf_tmp2, CHAR_SET_FAILED, 1) == 0)) {
338f08c3bdfSopenharmony_ci		/*
339f08c3bdfSopenharmony_ci		 * Problems were encountered in the set up of one of the children.
340f08c3bdfSopenharmony_ci		 * The error message has been displayed by the child.
341f08c3bdfSopenharmony_ci		 */
342f08c3bdfSopenharmony_ci		(void)par_kill();
343f08c3bdfSopenharmony_ci		cleanup();
344f08c3bdfSopenharmony_ci	}
345f08c3bdfSopenharmony_ci
346f08c3bdfSopenharmony_ci	/*
347f08c3bdfSopenharmony_ci	 *  Setup passed, now send SIGUSR1 to process id of zero.
348f08c3bdfSopenharmony_ci	 */
349f08c3bdfSopenharmony_ci	TEST(kill(0, SIGUSR1));
350f08c3bdfSopenharmony_ci
351f08c3bdfSopenharmony_ci	if (TEST_RETURN == -1) {
352f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TTERRNO, NULL, "kill() failed");
353f08c3bdfSopenharmony_ci		(void)par_kill();
354f08c3bdfSopenharmony_ci		cleanup();
355f08c3bdfSopenharmony_ci	}
356f08c3bdfSopenharmony_ci
357f08c3bdfSopenharmony_ci	/*
358f08c3bdfSopenharmony_ci	 *  Sleep for a while to allow the children to get a chance to
359f08c3bdfSopenharmony_ci	 *  catch the signal.
360f08c3bdfSopenharmony_ci	 */
361f08c3bdfSopenharmony_ci	(void)sleep(SLEEP_TIME);
362f08c3bdfSopenharmony_ci
363f08c3bdfSopenharmony_ci	/*
364f08c3bdfSopenharmony_ci	 *  The signal was sent above and time has run out for child response,
365f08c3bdfSopenharmony_ci	 *  check the outcomes.
366f08c3bdfSopenharmony_ci	 */
367f08c3bdfSopenharmony_ci	read1_stat = read(pipe1_fd[0], pipe_buf, 1);
368f08c3bdfSopenharmony_ci	if (read1_stat == -1 && errno == EAGAIN)
369f08c3bdfSopenharmony_ci		read1_stat = 0;
370f08c3bdfSopenharmony_ci	read2_stat = read(pipe2_fd[0], pipe_buf, 1);
371f08c3bdfSopenharmony_ci	if (read2_stat == -1 && errno == EAGAIN)
372f08c3bdfSopenharmony_ci		read2_stat = 0;
373f08c3bdfSopenharmony_ci	readA_stat = read(pipeA_fd[0], pipe_buf, 1);
374f08c3bdfSopenharmony_ci	if (readA_stat == -1 && errno == EAGAIN)
375f08c3bdfSopenharmony_ci		readA_stat = 0;
376f08c3bdfSopenharmony_ci	readB_stat = read(pipeB_fd[0], pipe_buf, 1);
377f08c3bdfSopenharmony_ci	if (readB_stat == -1 && errno == EAGAIN)
378f08c3bdfSopenharmony_ci		readB_stat = 0;
379f08c3bdfSopenharmony_ci
380f08c3bdfSopenharmony_ci	if (read1_stat == -1 || read2_stat == -1 ||
381f08c3bdfSopenharmony_ci	    readA_stat == -1 || readB_stat == -1) {
382f08c3bdfSopenharmony_ci		/*
383f08c3bdfSopenharmony_ci		 * The read system call failed.
384f08c3bdfSopenharmony_ci		 */
385f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, NULL, "read() failed");
386f08c3bdfSopenharmony_ci		(void)par_kill();
387f08c3bdfSopenharmony_ci		cleanup();
388f08c3bdfSopenharmony_ci	}
389f08c3bdfSopenharmony_ci
390f08c3bdfSopenharmony_ci	/*
391f08c3bdfSopenharmony_ci	 * Check the processes that were supposed to get the signal.
392f08c3bdfSopenharmony_ci	 */
393f08c3bdfSopenharmony_ci	if (read1_stat == SIG_RECEIVED) {
394f08c3bdfSopenharmony_ci		if (readA_stat == SIG_RECEIVED) {
395f08c3bdfSopenharmony_ci			/*
396f08c3bdfSopenharmony_ci			 *  Both processes, 1 and A, that were supposed to receive
397f08c3bdfSopenharmony_ci			 *  the signal did receive the signal.
398f08c3bdfSopenharmony_ci			 */
399f08c3bdfSopenharmony_ci			tst_resm(TPASS,
400f08c3bdfSopenharmony_ci				 "The signal was sent to all processes in the process group.");
401f08c3bdfSopenharmony_ci		} else {	/*Process A didn't receive the signal. */
402f08c3bdfSopenharmony_ci			tst_resm(TFAIL,
403f08c3bdfSopenharmony_ci				 "Process A did not receive the signal.");
404f08c3bdfSopenharmony_ci		}
405f08c3bdfSopenharmony_ci
406f08c3bdfSopenharmony_ci	} else {		/*Process 1 didn't receive the signal. */
407f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "Process 1 did not receive the signal.");
408f08c3bdfSopenharmony_ci	}
409f08c3bdfSopenharmony_ci
410f08c3bdfSopenharmony_ci	/*
411f08c3bdfSopenharmony_ci	 * Check the processes that were not supposed to get the signal.
412f08c3bdfSopenharmony_ci	 */
413f08c3bdfSopenharmony_ci	if (read2_stat == SIG_NOT_RECD) {
414f08c3bdfSopenharmony_ci		if (readB_stat == SIG_NOT_RECD) {
415f08c3bdfSopenharmony_ci			/*
416f08c3bdfSopenharmony_ci			 *  Both processes, 2 and B did not receive the signal.
417f08c3bdfSopenharmony_ci			 */
418f08c3bdfSopenharmony_ci			tst_resm(TPASS,
419f08c3bdfSopenharmony_ci				 "The signal was not sent to selective processes that were not in the process group.");
420f08c3bdfSopenharmony_ci		} else {	/*Process B received the signal. */
421f08c3bdfSopenharmony_ci			tst_resm(TFAIL, "Process B received the signal.");
422f08c3bdfSopenharmony_ci		}
423f08c3bdfSopenharmony_ci
424f08c3bdfSopenharmony_ci	}
425f08c3bdfSopenharmony_ci
426f08c3bdfSopenharmony_ci	else {			/*Process 2 received the signal. */
427f08c3bdfSopenharmony_ci
428f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "Process 2 received the signal.");
429f08c3bdfSopenharmony_ci	}
430f08c3bdfSopenharmony_ci
431f08c3bdfSopenharmony_ci	(void)par_kill();
432f08c3bdfSopenharmony_ci
433f08c3bdfSopenharmony_ci	(void)alarm(TIMEOUT);
434f08c3bdfSopenharmony_ci	while ((read(pipe1_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
435f08c3bdfSopenharmony_ci		strncpy(buf_tmp1, pipe_buf, 1);
436f08c3bdfSopenharmony_ci
437f08c3bdfSopenharmony_ci}				/*End of parent_rout */
438f08c3bdfSopenharmony_ci
439f08c3bdfSopenharmony_civoid child1_rout(void)
440f08c3bdfSopenharmony_ci{
441f08c3bdfSopenharmony_ci	who_am_i = '1';
442f08c3bdfSopenharmony_ci
443f08c3bdfSopenharmony_ci	/*
444f08c3bdfSopenharmony_ci	 *  Set to catch the SIGUSR1 with int1_rout.
445f08c3bdfSopenharmony_ci	 */
446f08c3bdfSopenharmony_ci	if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
447f08c3bdfSopenharmony_ci		tst_brkm(TBROK, NULL,
448f08c3bdfSopenharmony_ci			 "Could not set to catch the childrens signal.");
449f08c3bdfSopenharmony_ci		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
450f08c3bdfSopenharmony_ci		exit(0);
451f08c3bdfSopenharmony_ci	}
452f08c3bdfSopenharmony_ci	/*
453f08c3bdfSopenharmony_ci	 *  Create children A & B.
454f08c3bdfSopenharmony_ci	 */
455f08c3bdfSopenharmony_ci	if ((pidA = FORK_OR_VFORK()) > 0) {
456f08c3bdfSopenharmony_ci		/*
457f08c3bdfSopenharmony_ci		 *  This is the parent(child1), fork again to create child B.
458f08c3bdfSopenharmony_ci		 */
459f08c3bdfSopenharmony_ci		if ((pidB = FORK_OR_VFORK()) == 0) {
460f08c3bdfSopenharmony_ci			/* This is child B. */
461f08c3bdfSopenharmony_ci#ifdef UCLINUX
462f08c3bdfSopenharmony_ci			if (self_exec(argv0, "nd", 2, pipeB_fd[1]) < 0) {
463f08c3bdfSopenharmony_ci				tst_brkm(TBROK | TERRNO, NULL,
464f08c3bdfSopenharmony_ci					 "self_exec() failed");
465f08c3bdfSopenharmony_ci				(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
466f08c3bdfSopenharmony_ci				exit(0);
467f08c3bdfSopenharmony_ci			}
468f08c3bdfSopenharmony_ci#else
469f08c3bdfSopenharmony_ci			(void)childB_rout();
470f08c3bdfSopenharmony_ci#endif
471f08c3bdfSopenharmony_ci		}
472f08c3bdfSopenharmony_ci
473f08c3bdfSopenharmony_ci		else if (pidB == -1) {
474f08c3bdfSopenharmony_ci			/*
475f08c3bdfSopenharmony_ci			 *  The fork of child B failed kill child A.
476f08c3bdfSopenharmony_ci			 */
477f08c3bdfSopenharmony_ci			if (kill(pidA, SIGKILL) == -1)
478f08c3bdfSopenharmony_ci				tst_resm(TWARN,
479f08c3bdfSopenharmony_ci					 "Child process may not have been killed.");
480f08c3bdfSopenharmony_ci			tst_brkm(TBROK | TERRNO, NULL, "fork failed");
481f08c3bdfSopenharmony_ci			(void)write(pipe2_fd[1], CHAR_SET_FAILED, 1);
482f08c3bdfSopenharmony_ci			exit(0);
483f08c3bdfSopenharmony_ci		}
484f08c3bdfSopenharmony_ci	}
485f08c3bdfSopenharmony_ci
486f08c3bdfSopenharmony_ci	else if (pidA == 0) {
487f08c3bdfSopenharmony_ci		/* This is child A. */
488f08c3bdfSopenharmony_ci#ifdef UCLINUX
489f08c3bdfSopenharmony_ci		if (self_exec(argv0, "nd", 1, pipeA_fd[1]) < 0) {
490f08c3bdfSopenharmony_ci			tst_brkm(TBROK | TERRNO, NULL, "self_exec() failed");
491f08c3bdfSopenharmony_ci			(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
492f08c3bdfSopenharmony_ci			exit(0);
493f08c3bdfSopenharmony_ci		}
494f08c3bdfSopenharmony_ci#else
495f08c3bdfSopenharmony_ci		(void)childA_rout();
496f08c3bdfSopenharmony_ci#endif
497f08c3bdfSopenharmony_ci
498f08c3bdfSopenharmony_ci	}
499f08c3bdfSopenharmony_ci
500f08c3bdfSopenharmony_ci	else if (pidA == -1) {
501f08c3bdfSopenharmony_ci		/*
502f08c3bdfSopenharmony_ci		 *  The fork of child A failed.
503f08c3bdfSopenharmony_ci		 */
504f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, NULL, "fork failed");
505f08c3bdfSopenharmony_ci		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
506f08c3bdfSopenharmony_ci		exit(0);
507f08c3bdfSopenharmony_ci	}
508f08c3bdfSopenharmony_ci
509f08c3bdfSopenharmony_ci	/*
510f08c3bdfSopenharmony_ci	 *  Set to catch the SIGUSR2 with chld1_kill.
511f08c3bdfSopenharmony_ci	 */
512f08c3bdfSopenharmony_ci	if (signal(SIGUSR2, chld1_kill) == SIG_ERR) {
513f08c3bdfSopenharmony_ci		tst_brkm(TBROK, NULL,
514f08c3bdfSopenharmony_ci			 "Could not set to catch the parents signal.");
515f08c3bdfSopenharmony_ci		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
516f08c3bdfSopenharmony_ci		(void)chld1_kill();
517f08c3bdfSopenharmony_ci		exit(0);
518f08c3bdfSopenharmony_ci	}
519f08c3bdfSopenharmony_ci
520f08c3bdfSopenharmony_ci	/*
521f08c3bdfSopenharmony_ci	 *  Set to catch the alarm signal SIGALRM.
522f08c3bdfSopenharmony_ci	 */
523f08c3bdfSopenharmony_ci	if (signal(SIGALRM, notify_timeout) == SIG_ERR) {
524f08c3bdfSopenharmony_ci		tst_brkm(TBROK, NULL,
525f08c3bdfSopenharmony_ci			 "Could not set to catch the childs time out alarm.");
526f08c3bdfSopenharmony_ci		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
527f08c3bdfSopenharmony_ci		(void)chld1_kill();
528f08c3bdfSopenharmony_ci		exit(0);
529f08c3bdfSopenharmony_ci	}
530f08c3bdfSopenharmony_ci
531f08c3bdfSopenharmony_ci	/*
532f08c3bdfSopenharmony_ci	 *  Setting to catch the signals worked now let the children start up.
533f08c3bdfSopenharmony_ci	 *  Set an alarm which causes a time out on the pipe read loop.
534f08c3bdfSopenharmony_ci	 *  The children A & B will notify the parent(child1) that set up is complete
535f08c3bdfSopenharmony_ci	 *  and the pass/fail status of set up.
536f08c3bdfSopenharmony_ci	 */
537f08c3bdfSopenharmony_ci	(void)alarm(TIMEOUT - 40);
538f08c3bdfSopenharmony_ci
539f08c3bdfSopenharmony_ci	while ((read(pipeA_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
540f08c3bdfSopenharmony_ci		/*EMPTY*/;
541f08c3bdfSopenharmony_ci	(void)alarm(TIMEOUT - 40);
542f08c3bdfSopenharmony_ci
543f08c3bdfSopenharmony_ci	while ((read(pipeB_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
544f08c3bdfSopenharmony_ci		/*EMPTY*/;
545f08c3bdfSopenharmony_ci	(void)alarm(0);		/*Reset the alarm clock. */
546f08c3bdfSopenharmony_ci
547f08c3bdfSopenharmony_ci	/*
548f08c3bdfSopenharmony_ci	 *  Check the alarm flag.
549f08c3bdfSopenharmony_ci	 */
550f08c3bdfSopenharmony_ci	if (alarm_flag == TRUE) {
551f08c3bdfSopenharmony_ci		tst_brkm(TBROK, NULL,
552f08c3bdfSopenharmony_ci			 "The set up of the children failed by timing out.");
553f08c3bdfSopenharmony_ci		(void)chld1_kill();
554f08c3bdfSopenharmony_ci		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
555f08c3bdfSopenharmony_ci		exit(0);
556f08c3bdfSopenharmony_ci	}
557f08c3bdfSopenharmony_ci
558f08c3bdfSopenharmony_ci	/*
559f08c3bdfSopenharmony_ci	 *  Send a set up complete message to the parent.
560f08c3bdfSopenharmony_ci	 */
561f08c3bdfSopenharmony_ci	(void)write(pipe1_fd[1], CHAR_SET_PASSED, 1);
562f08c3bdfSopenharmony_ci
563f08c3bdfSopenharmony_ci	/*
564f08c3bdfSopenharmony_ci	 *  Pause until the signal SIGUSR1 or SIGUSR2 is sent from the parent.
565f08c3bdfSopenharmony_ci	 */
566f08c3bdfSopenharmony_ci	(void)pause();
567f08c3bdfSopenharmony_ci
568f08c3bdfSopenharmony_ci	/*
569f08c3bdfSopenharmony_ci	 *  Pause until signal SIGUSR2 is sent from the parent.
570f08c3bdfSopenharmony_ci	 *  This pause will only be executed if SIGUSR2 has not been received yet.
571f08c3bdfSopenharmony_ci	 */
572f08c3bdfSopenharmony_ci	while (1) {
573f08c3bdfSopenharmony_ci		sleep(1);
574f08c3bdfSopenharmony_ci	}
575f08c3bdfSopenharmony_ci
576f08c3bdfSopenharmony_ci}				/*End of child1_rout */
577f08c3bdfSopenharmony_ci
578f08c3bdfSopenharmony_ci/*******************************************************************************
579f08c3bdfSopenharmony_ci *  This is the routine for child 2, which should not receive the parents signal.
580f08c3bdfSopenharmony_ci ******************************************************************************/
581f08c3bdfSopenharmony_civoid child2_rout(void)
582f08c3bdfSopenharmony_ci{
583f08c3bdfSopenharmony_ci	who_am_i = '2';
584f08c3bdfSopenharmony_ci
585f08c3bdfSopenharmony_ci	/*
586f08c3bdfSopenharmony_ci	 * Set the process group of this process to be different
587f08c3bdfSopenharmony_ci	 * than the other processes.
588f08c3bdfSopenharmony_ci	 */
589f08c3bdfSopenharmony_ci	(void)setpgrp();
590f08c3bdfSopenharmony_ci
591f08c3bdfSopenharmony_ci	/*
592f08c3bdfSopenharmony_ci	 *  Set to catch the SIGUSR1 with usr1_rout.
593f08c3bdfSopenharmony_ci	 */
594f08c3bdfSopenharmony_ci	if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
595f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup,
596f08c3bdfSopenharmony_ci			 "Could not set to catch the parents signal.");
597f08c3bdfSopenharmony_ci		(void)write(pipe2_fd[1], CHAR_SET_FAILED, 1);
598f08c3bdfSopenharmony_ci		exit(0);
599f08c3bdfSopenharmony_ci	}
600f08c3bdfSopenharmony_ci
601f08c3bdfSopenharmony_ci	/* Send a set up complete message to parent. */
602f08c3bdfSopenharmony_ci	(void)write(pipe2_fd[1], CHAR_SET_PASSED, 1);
603f08c3bdfSopenharmony_ci
604f08c3bdfSopenharmony_ci	/*
605f08c3bdfSopenharmony_ci	 *  Pause until killed by the parent or SIGUSR1 is received.
606f08c3bdfSopenharmony_ci	 */
607f08c3bdfSopenharmony_ci	(void)pause();
608f08c3bdfSopenharmony_ci}
609f08c3bdfSopenharmony_ci
610f08c3bdfSopenharmony_ci/*******************************************************************************
611f08c3bdfSopenharmony_ci *  This is the routine for child A, which should receive the parents signal.
612f08c3bdfSopenharmony_ci ******************************************************************************/
613f08c3bdfSopenharmony_civoid childA_rout(void)
614f08c3bdfSopenharmony_ci{
615f08c3bdfSopenharmony_ci	who_am_i = 'A';
616f08c3bdfSopenharmony_ci
617f08c3bdfSopenharmony_ci	/* Send a set up complete message to parent. */
618f08c3bdfSopenharmony_ci	write(pipeA_fd[1], CHAR_SET_PASSED, 1);
619f08c3bdfSopenharmony_ci
620f08c3bdfSopenharmony_ci	/*
621f08c3bdfSopenharmony_ci	 *  Pause until killed by the parent or SIGUSR1 is received.
622f08c3bdfSopenharmony_ci	 */
623f08c3bdfSopenharmony_ci	(void)pause();
624f08c3bdfSopenharmony_ci
625f08c3bdfSopenharmony_ci	exit(0);
626f08c3bdfSopenharmony_ci}				/*End of childA_rout */
627f08c3bdfSopenharmony_ci
628f08c3bdfSopenharmony_ci#ifdef UCLINUX
629f08c3bdfSopenharmony_ci/*******************************************************************************
630f08c3bdfSopenharmony_ci *  This is the routine for child A after self_exec
631f08c3bdfSopenharmony_ci ******************************************************************************/
632f08c3bdfSopenharmony_civoid childA_rout_uclinux(void)
633f08c3bdfSopenharmony_ci{
634f08c3bdfSopenharmony_ci	/* Setup the signal handler again */
635f08c3bdfSopenharmony_ci	if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
636f08c3bdfSopenharmony_ci		tst_brkm(TBROK, NULL,
637f08c3bdfSopenharmony_ci			 "Could not set to catch the childrens signal.");
638f08c3bdfSopenharmony_ci		(void)write(pipeA_fd[1], CHAR_SET_FAILED, 1);
639f08c3bdfSopenharmony_ci		exit(0);
640f08c3bdfSopenharmony_ci	}
641f08c3bdfSopenharmony_ci
642f08c3bdfSopenharmony_ci	childA_rout();
643f08c3bdfSopenharmony_ci}
644f08c3bdfSopenharmony_ci#endif
645f08c3bdfSopenharmony_ci
646f08c3bdfSopenharmony_ci/*******************************************************************************
647f08c3bdfSopenharmony_ci *  This is the routine for child B, which should not receive the parents signal.
648f08c3bdfSopenharmony_ci ******************************************************************************/
649f08c3bdfSopenharmony_civoid childB_rout(void)
650f08c3bdfSopenharmony_ci{
651f08c3bdfSopenharmony_ci	who_am_i = 'B';
652f08c3bdfSopenharmony_ci
653f08c3bdfSopenharmony_ci	/*
654f08c3bdfSopenharmony_ci	 * Set the process group of this process to be different
655f08c3bdfSopenharmony_ci	 * than the other processes.
656f08c3bdfSopenharmony_ci	 */
657f08c3bdfSopenharmony_ci	(void)setpgrp();
658f08c3bdfSopenharmony_ci
659f08c3bdfSopenharmony_ci	/* Send a set up complete message to parent(child 1). */
660f08c3bdfSopenharmony_ci	write(pipeB_fd[1], CHAR_SET_PASSED, 1);
661f08c3bdfSopenharmony_ci
662f08c3bdfSopenharmony_ci	/*
663f08c3bdfSopenharmony_ci	 *  Pause until killed by the parent(child 1) or SIGUSR1 is received.
664f08c3bdfSopenharmony_ci	 */
665f08c3bdfSopenharmony_ci	(void)pause();
666f08c3bdfSopenharmony_ci
667f08c3bdfSopenharmony_ci	exit(0);
668f08c3bdfSopenharmony_ci}
669f08c3bdfSopenharmony_ci
670f08c3bdfSopenharmony_ci#ifdef UCLINUX
671f08c3bdfSopenharmony_ci/*******************************************************************************
672f08c3bdfSopenharmony_ci *  This is the routine for child B after self_exec
673f08c3bdfSopenharmony_ci ******************************************************************************/
674f08c3bdfSopenharmony_civoid childB_rout_uclinux(void)
675f08c3bdfSopenharmony_ci{
676f08c3bdfSopenharmony_ci	/* Setup the signal handler again */
677f08c3bdfSopenharmony_ci	if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
678f08c3bdfSopenharmony_ci		tst_brkm(TBROK, NULL,
679f08c3bdfSopenharmony_ci			 "Could not set to catch the childrens signal.");
680f08c3bdfSopenharmony_ci		(void)write(pipeB_fd[1], CHAR_SET_FAILED, 1);
681f08c3bdfSopenharmony_ci		exit(0);
682f08c3bdfSopenharmony_ci	}
683f08c3bdfSopenharmony_ci
684f08c3bdfSopenharmony_ci	childB_rout();
685f08c3bdfSopenharmony_ci}
686f08c3bdfSopenharmony_ci#endif
687f08c3bdfSopenharmony_ci
688f08c3bdfSopenharmony_ci/*******************************************************************************
689f08c3bdfSopenharmony_ci *  This routine sets up the interprocess communication pipes, signal handling,
690f08c3bdfSopenharmony_ci *  and process group information.
691f08c3bdfSopenharmony_ci ******************************************************************************/
692f08c3bdfSopenharmony_civoid setup(void)
693f08c3bdfSopenharmony_ci{
694f08c3bdfSopenharmony_ci	int errno_buf;		/*indicates the errno if pipe set up fails.             */
695f08c3bdfSopenharmony_ci	int err_flag = FALSE;	/*Indicates if an error has occurred in pipe set up.    */
696f08c3bdfSopenharmony_ci
697f08c3bdfSopenharmony_ci	/*
698f08c3bdfSopenharmony_ci	 *  Set the process group ID to be equal between the parent and children.
699f08c3bdfSopenharmony_ci	 */
700f08c3bdfSopenharmony_ci	(void)setpgrp();
701f08c3bdfSopenharmony_ci
702f08c3bdfSopenharmony_ci	/*
703f08c3bdfSopenharmony_ci	 *  Set to catch unexpected signals.
704f08c3bdfSopenharmony_ci	 *  SIGCHLD is set to be ignored because we do not wait for termination status.
705f08c3bdfSopenharmony_ci	 *  SIGUSR1 is set to be ignored because this is the signal we are using for
706f08c3bdfSopenharmony_ci	 *  the test and we are not concerned with the parent getting it.
707f08c3bdfSopenharmony_ci	 */
708f08c3bdfSopenharmony_ci
709f08c3bdfSopenharmony_ci	tst_sig(FORK, DEF_HANDLER, cleanup);
710f08c3bdfSopenharmony_ci
711f08c3bdfSopenharmony_ci	if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
712f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TFAIL, NULL,
713f08c3bdfSopenharmony_ci			 "signal(SIGUSR1, SIG_IGN) failed");
714f08c3bdfSopenharmony_ci	}
715f08c3bdfSopenharmony_ci
716f08c3bdfSopenharmony_ci	if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
717f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, NULL,
718f08c3bdfSopenharmony_ci			 "signal(SIGCHLD, SIG_IGN) failed");
719f08c3bdfSopenharmony_ci	}
720f08c3bdfSopenharmony_ci
721f08c3bdfSopenharmony_ci	TEST_PAUSE;
722f08c3bdfSopenharmony_ci
723f08c3bdfSopenharmony_ci	/*
724f08c3bdfSopenharmony_ci	 *  Set up pipe1, pipe2, pipeA, and pipeB.
725f08c3bdfSopenharmony_ci	 */
726f08c3bdfSopenharmony_ci	if ((pipe(pipe1_fd) == -1)
727f08c3bdfSopenharmony_ci	    || (fcntl(pipe1_fd[0], F_SETFL, O_NDELAY) == -1)) {
728f08c3bdfSopenharmony_ci		errno_buf = errno;
729f08c3bdfSopenharmony_ci		err_flag = TRUE;
730f08c3bdfSopenharmony_ci	}
731f08c3bdfSopenharmony_ci
732f08c3bdfSopenharmony_ci	if ((pipe(pipe2_fd) == -1)
733f08c3bdfSopenharmony_ci	    || (fcntl(pipe2_fd[0], F_SETFL, O_NDELAY) == -1)) {
734f08c3bdfSopenharmony_ci		errno_buf = errno;
735f08c3bdfSopenharmony_ci		err_flag = TRUE;
736f08c3bdfSopenharmony_ci	}
737f08c3bdfSopenharmony_ci
738f08c3bdfSopenharmony_ci	if ((pipe(pipeA_fd) == -1)
739f08c3bdfSopenharmony_ci	    || (fcntl(pipeA_fd[0], F_SETFL, O_NDELAY) == -1)) {
740f08c3bdfSopenharmony_ci		errno_buf = errno;
741f08c3bdfSopenharmony_ci		err_flag = TRUE;
742f08c3bdfSopenharmony_ci	}
743f08c3bdfSopenharmony_ci
744f08c3bdfSopenharmony_ci	if ((pipe(pipeB_fd) == -1)
745f08c3bdfSopenharmony_ci	    || (fcntl(pipeB_fd[0], F_SETFL, O_NDELAY) == -1)) {
746f08c3bdfSopenharmony_ci		errno_buf = errno;
747f08c3bdfSopenharmony_ci		err_flag = TRUE;
748f08c3bdfSopenharmony_ci	}
749f08c3bdfSopenharmony_ci
750f08c3bdfSopenharmony_ci	/*
751f08c3bdfSopenharmony_ci	 *  Check for errors.
752f08c3bdfSopenharmony_ci	 */
753f08c3bdfSopenharmony_ci	if (err_flag == TRUE) {
754f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, NULL, "pipe() failed");
755f08c3bdfSopenharmony_ci	}
756f08c3bdfSopenharmony_ci	return;
757f08c3bdfSopenharmony_ci
758f08c3bdfSopenharmony_ci}
759f08c3bdfSopenharmony_ci
760f08c3bdfSopenharmony_ci/***********************************************************
761f08c3bdfSopenharmony_ci *  This routine indicates that the process caught SIGUSR1.
762f08c3bdfSopenharmony_ci **********************************************************/
763f08c3bdfSopenharmony_civoid usr1_rout(void)
764f08c3bdfSopenharmony_ci{
765f08c3bdfSopenharmony_ci	switch (who_am_i) {
766f08c3bdfSopenharmony_ci	case '1':
767f08c3bdfSopenharmony_ci		if (write(pipe1_fd[1], SIG_CAUGHT, 1) == -1)
768f08c3bdfSopenharmony_ci			tst_resm(TWARN,
769f08c3bdfSopenharmony_ci				 "Writing signal catching status failed in child 1.");
770f08c3bdfSopenharmony_ci		break;
771f08c3bdfSopenharmony_ci	case '2':
772f08c3bdfSopenharmony_ci		if (write(pipe2_fd[1], SIG_CAUGHT, 1) == -1)
773f08c3bdfSopenharmony_ci			tst_resm(TWARN,
774f08c3bdfSopenharmony_ci				 "Writing signal catching status failed in child 2.");
775f08c3bdfSopenharmony_ci		break;
776f08c3bdfSopenharmony_ci	case 'A':
777f08c3bdfSopenharmony_ci		if (write(pipeA_fd[1], SIG_CAUGHT, 1) == -1)
778f08c3bdfSopenharmony_ci			tst_resm(TWARN,
779f08c3bdfSopenharmony_ci				 "Writing signal catching status failed in child A.");
780f08c3bdfSopenharmony_ci		break;
781f08c3bdfSopenharmony_ci	case 'B':
782f08c3bdfSopenharmony_ci		if (write(pipeB_fd[1], SIG_CAUGHT, 1) == -1)
783f08c3bdfSopenharmony_ci			tst_resm(TWARN,
784f08c3bdfSopenharmony_ci				 "Writing signal catching status failed in child B.");
785f08c3bdfSopenharmony_ci		break;
786f08c3bdfSopenharmony_ci	default:
787f08c3bdfSopenharmony_ci		tst_resm(TWARN,
788f08c3bdfSopenharmony_ci			 "Unexpected value %d for who_am_i in usr1_rout()",
789f08c3bdfSopenharmony_ci			 who_am_i);
790f08c3bdfSopenharmony_ci		break;
791f08c3bdfSopenharmony_ci	}
792f08c3bdfSopenharmony_ci
793f08c3bdfSopenharmony_ci}				/*End of usr1_rout */
794f08c3bdfSopenharmony_ci
795f08c3bdfSopenharmony_ci/***********************************************************
796f08c3bdfSopenharmony_ci *  This routine handles the timeout alarm in the parent,
797f08c3bdfSopenharmony_ci *  which occurs when the child fails to notify the parent
798f08c3bdfSopenharmony_ci *  the status of set up.
799f08c3bdfSopenharmony_ci **********************************************************/
800f08c3bdfSopenharmony_civoid notify_timeout(void)
801f08c3bdfSopenharmony_ci{
802f08c3bdfSopenharmony_ci	alarm_flag = TRUE;
803f08c3bdfSopenharmony_ci
804f08c3bdfSopenharmony_ci}				/*End of notify_timeout */
805f08c3bdfSopenharmony_ci
806f08c3bdfSopenharmony_ci/***********************************************************
807f08c3bdfSopenharmony_ci *  This routine handles the procedure for removing the
808f08c3bdfSopenharmony_ci *  children forked off during this test.
809f08c3bdfSopenharmony_ci **********************************************************/
810f08c3bdfSopenharmony_civoid par_kill(void)
811f08c3bdfSopenharmony_ci{
812f08c3bdfSopenharmony_ci	int status;
813f08c3bdfSopenharmony_ci
814f08c3bdfSopenharmony_ci	/*
815f08c3bdfSopenharmony_ci	 *  Indicate to child1 that it can remove it's children and itself now.
816f08c3bdfSopenharmony_ci	 */
817f08c3bdfSopenharmony_ci	if (kill(pid1, SIGUSR2) == -1 && errno != ESRCH) {
818f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "kill() failed");
819f08c3bdfSopenharmony_ci		tst_resm(TWARN,
820f08c3bdfSopenharmony_ci			 "Child 1 and it's children may still be alive.");
821f08c3bdfSopenharmony_ci	}
822f08c3bdfSopenharmony_ci
823f08c3bdfSopenharmony_ci	/*
824f08c3bdfSopenharmony_ci	 *  Remove child 2.
825f08c3bdfSopenharmony_ci	 */
826f08c3bdfSopenharmony_ci	if (kill(pid2, SIGKILL) == -1 && errno != ESRCH)
827f08c3bdfSopenharmony_ci		tst_resm(TWARN, "Child2 may still be alive.");
828f08c3bdfSopenharmony_ci
829f08c3bdfSopenharmony_ci	wait(&status);
830f08c3bdfSopenharmony_ci	return;
831f08c3bdfSopenharmony_ci
832f08c3bdfSopenharmony_ci}				/*End of par_kill */
833f08c3bdfSopenharmony_ci
834f08c3bdfSopenharmony_ci/*********************************************************************
835f08c3bdfSopenharmony_ci *  This routine is executed by child 1 when the parent tells it to
836f08c3bdfSopenharmony_ci *  remove it's children and itself.
837f08c3bdfSopenharmony_ci ********************************************************************/
838f08c3bdfSopenharmony_civoid chld1_kill(void)
839f08c3bdfSopenharmony_ci{
840f08c3bdfSopenharmony_ci	/*
841f08c3bdfSopenharmony_ci	 *  Remove children A & B.
842f08c3bdfSopenharmony_ci	 */
843f08c3bdfSopenharmony_ci	if (kill(pidA, SIGKILL) == -1 && errno != ESRCH)
844f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO,
845f08c3bdfSopenharmony_ci			 "kill(%d) failed; child 1's(A) child may still be alive",
846f08c3bdfSopenharmony_ci			 pidA);
847f08c3bdfSopenharmony_ci
848f08c3bdfSopenharmony_ci	(void)write(pipe1_fd[1], CHAR_SET_PASSED, 1);
849f08c3bdfSopenharmony_ci
850f08c3bdfSopenharmony_ci	if (kill(pidB, SIGKILL) == -1 && errno != ESRCH)
851f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO,
852f08c3bdfSopenharmony_ci			 "kill(%d) failed; child 1's(B) child may still be alive",
853f08c3bdfSopenharmony_ci			 pidB);
854f08c3bdfSopenharmony_ci
855f08c3bdfSopenharmony_ci	exit(0);
856f08c3bdfSopenharmony_ci
857f08c3bdfSopenharmony_ci}				/*End of chld1_kill */
858f08c3bdfSopenharmony_ci
859f08c3bdfSopenharmony_ci/***************************************************************
860f08c3bdfSopenharmony_ci * cleanup() - performs all ONE TIME cleanup for this test at
861f08c3bdfSopenharmony_ci *              completion or premature exit.
862f08c3bdfSopenharmony_ci ***************************************************************/
863f08c3bdfSopenharmony_civoid cleanup(void)
864f08c3bdfSopenharmony_ci{
865f08c3bdfSopenharmony_ci
866f08c3bdfSopenharmony_ci}
867