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: sigrelse01.c,v 1.14 2009/08/28 14:10:16 vapier Exp $ */
34f08c3bdfSopenharmony_ci/*****************************************************************************
35f08c3bdfSopenharmony_ci * OS Test - Silicon Graphics, Inc.  Eagan, Minnesota
36f08c3bdfSopenharmony_ci *
37f08c3bdfSopenharmony_ci * TEST IDENTIFIER : sigrelse01 Releasing held signals.
38f08c3bdfSopenharmony_ci *
39f08c3bdfSopenharmony_ci * PARENT DOCUMENT : sgrtds01  sigrelse system call
40f08c3bdfSopenharmony_ci *
41f08c3bdfSopenharmony_ci * AUTHOR          : Bob Clark
42f08c3bdfSopenharmony_ci *		   : Rewrote 12/92 by Richard Logan
43f08c3bdfSopenharmony_ci *
44f08c3bdfSopenharmony_ci * CO-PILOT        : Dave Baumgartner
45f08c3bdfSopenharmony_ci *
46f08c3bdfSopenharmony_ci * DATE STARTED    : 10/08/86
47f08c3bdfSopenharmony_ci *
48f08c3bdfSopenharmony_ci * TEST ITEMS
49f08c3bdfSopenharmony_ci *
50f08c3bdfSopenharmony_ci * 	1. sigrelse turns on the receipt of signals held by sighold.
51f08c3bdfSopenharmony_ci *
52f08c3bdfSopenharmony_ci * SPECIAL PROCEDURAL REQUIRMENTS
53f08c3bdfSopenharmony_ci * 	None
54f08c3bdfSopenharmony_ci *
55f08c3bdfSopenharmony_ci * DETAILED DESCRIPTION
56f08c3bdfSopenharmony_ci * 	set up pipe for parent/child communications
57f08c3bdfSopenharmony_ci * 	fork off a child process
58f08c3bdfSopenharmony_ci *
59f08c3bdfSopenharmony_ci * 	parent():
60f08c3bdfSopenharmony_ci * 		set up for unexpected signals
61f08c3bdfSopenharmony_ci * 		wait for child to send ready message over pipe
62f08c3bdfSopenharmony_ci * 		send all catchable signals to child process
63f08c3bdfSopenharmony_ci *		send alarm signal to speed up timeout
64f08c3bdfSopenharmony_ci * 		wait for child to terminate and check exit value
65f08c3bdfSopenharmony_ci *
66f08c3bdfSopenharmony_ci * 		if exit value is EXIT_OK
67f08c3bdfSopenharmony_ci * 		  get message from pipe (contains array of signal counters)
68f08c3bdfSopenharmony_ci * 		  loop through array of signal counters and record any
69f08c3bdfSopenharmony_ci * 			signals which were not caught once.
70f08c3bdfSopenharmony_ci * 		  record PASS or FAIL depending on what was found in the array.
71f08c3bdfSopenharmony_ci *
72f08c3bdfSopenharmony_ci * 		else if exit is SIG_CAUGHT then BROK (signal caught
73f08c3bdfSopenharmony_ci *		  before released)
74f08c3bdfSopenharmony_ci * 		else if exit is WRITE_BROK then BROK (write() to pipe failed)
75f08c3bdfSopenharmony_ci * 		else if exit is HANDLE_ERR then BROK (error in child's
76f08c3bdfSopenharmony_ci *		  signal handler)
77f08c3bdfSopenharmony_ci * 		else unexpected exit value - BROK
78f08c3bdfSopenharmony_ci *
79f08c3bdfSopenharmony_ci * 	child():
80f08c3bdfSopenharmony_ci * 	  phase 1:
81f08c3bdfSopenharmony_ci * 		set up to catch all catchable signals (exit SIG_CAUGHT
82f08c3bdfSopenharmony_ci *		  if caught)
83f08c3bdfSopenharmony_ci * 		hold each signal with sighold()
84f08c3bdfSopenharmony_ci * 		send parent ready message if setup went ok.
85f08c3bdfSopenharmony_ci * 		wait for signals to arrive - timeout if they don't
86f08c3bdfSopenharmony_ci *
87f08c3bdfSopenharmony_ci * 	  phase 2:
88f08c3bdfSopenharmony_ci * 		release each signal and wait a second for the handler to
89f08c3bdfSopenharmony_ci *		  catch it.
90f08c3bdfSopenharmony_ci * 		(the handler will record each signal it catches in an array
91f08c3bdfSopenharmony_ci * 		and exit HANDLE_ERR if an error occurs)
92f08c3bdfSopenharmony_ci *
93f08c3bdfSopenharmony_ci * 		send array of counters back to parent for processing.
94f08c3bdfSopenharmony_ci * 		exit EXIT_OK
95f08c3bdfSopenharmony_ci * NOTES
96f08c3bdfSopenharmony_ci *	since child is executing system calls under test, no
97f08c3bdfSopenharmony_ci *	system call times are printed.
98f08c3bdfSopenharmony_ci *
99f08c3bdfSopenharmony_ci***************************************************************************/
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci#include <sys/types.h>
102f08c3bdfSopenharmony_ci#include <sys/wait.h>
103f08c3bdfSopenharmony_ci#include <errno.h>
104f08c3bdfSopenharmony_ci#include <fcntl.h>
105f08c3bdfSopenharmony_ci#include <signal.h>
106f08c3bdfSopenharmony_ci#include <stdlib.h>
107f08c3bdfSopenharmony_ci#include <string.h>
108f08c3bdfSopenharmony_ci#include <time.h>
109f08c3bdfSopenharmony_ci#include <unistd.h>
110f08c3bdfSopenharmony_ci#include "test.h"
111f08c3bdfSopenharmony_ci#include "safe_macros.h"
112f08c3bdfSopenharmony_ci
113f08c3bdfSopenharmony_ci#ifdef __linux__
114f08c3bdfSopenharmony_ci/* glibc2.2 definition needs -D_XOPEN_SOURCE, which breaks other things. */
115f08c3bdfSopenharmony_ciextern int sighold(int __sig);
116f08c3bdfSopenharmony_ciextern int sigrelse(int __sig);
117f08c3bdfSopenharmony_ci#endif
118f08c3bdfSopenharmony_ci
119f08c3bdfSopenharmony_ci/* Needed for NPTL */
120f08c3bdfSopenharmony_ci#define SIGCANCEL 32
121f08c3bdfSopenharmony_ci#define SIGTIMER 33
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_civoid setup(void);
124f08c3bdfSopenharmony_civoid cleanup(void);
125f08c3bdfSopenharmony_cistatic void parent(void);
126f08c3bdfSopenharmony_cistatic void child(void);
127f08c3bdfSopenharmony_cistatic void timeout(int sig);
128f08c3bdfSopenharmony_cistatic int setup_sigs(void);
129f08c3bdfSopenharmony_cistatic void handler(int sig);
130f08c3bdfSopenharmony_cistatic void wait_a_while(void);
131f08c3bdfSopenharmony_cistatic char *read_pipe(int fd);
132f08c3bdfSopenharmony_cistatic int write_pipe(int fd, char *msg);
133f08c3bdfSopenharmony_cistatic int set_timeout(void);
134f08c3bdfSopenharmony_cistatic void clear_timeout(void);
135f08c3bdfSopenharmony_cistatic void getout(void);
136f08c3bdfSopenharmony_ciint choose_sig(int sig);
137f08c3bdfSopenharmony_ci
138f08c3bdfSopenharmony_ci#define TRUE  1
139f08c3bdfSopenharmony_ci#define FALSE 0
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_ci#ifndef DEBUG
142f08c3bdfSopenharmony_ci#define DEBUG 0
143f08c3bdfSopenharmony_ci#endif
144f08c3bdfSopenharmony_ci
145f08c3bdfSopenharmony_ci#define CHILD_EXIT(VAL) ((VAL >> 8) & 0377)	/* exit value of child process */
146f08c3bdfSopenharmony_ci#define CHILD_SIG(VAL)   (VAL & 0377)	/* signal value of child proc */
147f08c3bdfSopenharmony_ci
148f08c3bdfSopenharmony_ci#define MAXMESG 512		/* the size of the message string */
149f08c3bdfSopenharmony_ci
150f08c3bdfSopenharmony_ci#define READY "ready"		/* signal to parent that child is set up */
151f08c3bdfSopenharmony_ci
152f08c3bdfSopenharmony_ci#define TIMEOUT 30		/* time (sec) used in the alarm calls */
153f08c3bdfSopenharmony_ci
154f08c3bdfSopenharmony_ci/* child exit values */
155f08c3bdfSopenharmony_ci#define EXIT_OK    0
156f08c3bdfSopenharmony_ci#define SIG_CAUGHT 8
157f08c3bdfSopenharmony_ci#define WRITE_BROK 16
158f08c3bdfSopenharmony_ci#define HANDLE_ERR 32
159f08c3bdfSopenharmony_ci
160f08c3bdfSopenharmony_ciint TST_TOTAL = 1;		/* number of test items */
161f08c3bdfSopenharmony_ci
162f08c3bdfSopenharmony_cichar *TCID = "sigrelse01";	/* test case identifier */
163f08c3bdfSopenharmony_cistatic char mesg[MAXMESG];	/* message buffer for tst_res */
164f08c3bdfSopenharmony_cistatic int pid;			/* process id of child */
165f08c3bdfSopenharmony_cistatic int pipe_fd[2];		/* file descriptors for pipe parent read */
166f08c3bdfSopenharmony_cistatic int pipe_fd2[2];		/* file descriptors for pipe child read */
167f08c3bdfSopenharmony_cistatic int phase;		/* flag for phase1 or phase2 of */
168f08c3bdfSopenharmony_ci				/* signal handler */
169f08c3bdfSopenharmony_cistatic int sig_caught;		/* flag TRUE if signal caught */
170f08c3bdfSopenharmony_ci				/* (see wait_a_while ()) */
171f08c3bdfSopenharmony_ci
172f08c3bdfSopenharmony_ci/* ensure that NUMSIGS is defined. */
173f08c3bdfSopenharmony_ci#ifndef NUMSIGS
174f08c3bdfSopenharmony_ci#define NUMSIGS NSIG
175f08c3bdfSopenharmony_ci#endif
176f08c3bdfSopenharmony_ci
177f08c3bdfSopenharmony_ci/* array of counters for signals caught by handler() */
178f08c3bdfSopenharmony_cistatic int sig_array[NUMSIGS];
179f08c3bdfSopenharmony_ci
180f08c3bdfSopenharmony_ci/***********************************************************************
181f08c3bdfSopenharmony_ci *   M A I N
182f08c3bdfSopenharmony_ci ***********************************************************************/
183f08c3bdfSopenharmony_ciint main(int argc, char **argv)
184f08c3bdfSopenharmony_ci{
185f08c3bdfSopenharmony_ci	int lc;
186f08c3bdfSopenharmony_ci
187f08c3bdfSopenharmony_ci	/* gcc -Wall complains about sig_caught not being ref'd because of the
188f08c3bdfSopenharmony_ci	   external declarations. */
189f08c3bdfSopenharmony_ci	sig_caught = FALSE;
190f08c3bdfSopenharmony_ci
191f08c3bdfSopenharmony_ci	/*
192f08c3bdfSopenharmony_ci	 * parse standard options
193f08c3bdfSopenharmony_ci	 */
194f08c3bdfSopenharmony_ci	tst_parse_opts(argc, argv, NULL, NULL);
195f08c3bdfSopenharmony_ci#ifdef UCLINUX
196f08c3bdfSopenharmony_ci	maybe_run_child(&child, "dd", &pipe_fd[1], &pipe_fd2[0]);
197f08c3bdfSopenharmony_ci#endif
198f08c3bdfSopenharmony_ci
199f08c3bdfSopenharmony_ci	/*
200f08c3bdfSopenharmony_ci	 * perform global setup for test
201f08c3bdfSopenharmony_ci	 */
202f08c3bdfSopenharmony_ci	setup();
203f08c3bdfSopenharmony_ci
204f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); lc++) {
205f08c3bdfSopenharmony_ci
206f08c3bdfSopenharmony_ci		tst_count = 0;
207f08c3bdfSopenharmony_ci
208f08c3bdfSopenharmony_ci		/*
209f08c3bdfSopenharmony_ci		 * fork off a child process
210f08c3bdfSopenharmony_ci		 */
211f08c3bdfSopenharmony_ci		if ((pid = FORK_OR_VFORK()) < 0) {
212f08c3bdfSopenharmony_ci			tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
213f08c3bdfSopenharmony_ci
214f08c3bdfSopenharmony_ci		} else if (pid > 0) {
215f08c3bdfSopenharmony_ci			parent();
216f08c3bdfSopenharmony_ci
217f08c3bdfSopenharmony_ci		} else {
218f08c3bdfSopenharmony_ci#ifdef UCLINUX
219f08c3bdfSopenharmony_ci			if (self_exec(argv[0], "dd", pipe_fd[1], pipe_fd2[0]) <
220f08c3bdfSopenharmony_ci			    0) {
221f08c3bdfSopenharmony_ci				tst_brkm(TBROK | TERRNO, cleanup,
222f08c3bdfSopenharmony_ci					 "self_exec() failed");
223f08c3bdfSopenharmony_ci			}
224f08c3bdfSopenharmony_ci#else
225f08c3bdfSopenharmony_ci			child();
226f08c3bdfSopenharmony_ci#endif
227f08c3bdfSopenharmony_ci		}
228f08c3bdfSopenharmony_ci
229f08c3bdfSopenharmony_ci	}
230f08c3bdfSopenharmony_ci
231f08c3bdfSopenharmony_ci	cleanup();
232f08c3bdfSopenharmony_ci	tst_exit();
233f08c3bdfSopenharmony_ci
234f08c3bdfSopenharmony_ci}				/* end main */
235f08c3bdfSopenharmony_ci
236f08c3bdfSopenharmony_ci/****************************************************************************
237f08c3bdfSopenharmony_ci * parent() : wait for "ready" from child, send signals to child, wait for
238f08c3bdfSopenharmony_ci *    child to exit and report what happened.
239f08c3bdfSopenharmony_ci ***************************************************************************/
240f08c3bdfSopenharmony_cistatic void parent(void)
241f08c3bdfSopenharmony_ci{
242f08c3bdfSopenharmony_ci	int term_stat;		/* child return status */
243f08c3bdfSopenharmony_ci	int rv;			/* function return value */
244f08c3bdfSopenharmony_ci	int sig;		/* current signal number */
245f08c3bdfSopenharmony_ci	char *str;		/* string returned from read_pipe() */
246f08c3bdfSopenharmony_ci	int *array;		/* pointer to sig_array returned from child */
247f08c3bdfSopenharmony_ci	int fail = FALSE;	/* flag indicating test item failure */
248f08c3bdfSopenharmony_ci	char big_mesg[MAXMESG * 6];	/* storage for big failure message */
249f08c3bdfSopenharmony_ci	int caught_sigs;
250f08c3bdfSopenharmony_ci
251f08c3bdfSopenharmony_ci	/* wait for "ready" message from child */
252f08c3bdfSopenharmony_ci	if ((str = read_pipe(pipe_fd[0])) == NULL) {
253f08c3bdfSopenharmony_ci		/* read_pipe() failed. */
254f08c3bdfSopenharmony_ci		tst_brkm(TBROK, getout, "%s", mesg);
255f08c3bdfSopenharmony_ci	}
256f08c3bdfSopenharmony_ci
257f08c3bdfSopenharmony_ci	if (strcmp(str, READY) != 0) {
258f08c3bdfSopenharmony_ci		/* child setup did not go well */
259f08c3bdfSopenharmony_ci		tst_brkm(TBROK, getout, "%s", str);
260f08c3bdfSopenharmony_ci	}
261f08c3bdfSopenharmony_ci
262f08c3bdfSopenharmony_ci	/*
263f08c3bdfSopenharmony_ci	 * send signals to child and see if it holds them
264f08c3bdfSopenharmony_ci	 */
265f08c3bdfSopenharmony_ci
266f08c3bdfSopenharmony_ci	for (sig = 1; sig < NUMSIGS; sig++) {
267f08c3bdfSopenharmony_ci		if (choose_sig(sig)) {
268f08c3bdfSopenharmony_ci			if (kill(pid, sig) < 0) {
269f08c3bdfSopenharmony_ci				if (errno == ESRCH) {
270f08c3bdfSopenharmony_ci					if (kill(pid, SIGTERM) < 0)
271f08c3bdfSopenharmony_ci						tst_brkm(TBROK | TERRNO, getout,
272f08c3bdfSopenharmony_ci							 "kill(%d, %d) and kill(%d, SIGTERM) failed",
273f08c3bdfSopenharmony_ci							 pid, sig, pid);
274f08c3bdfSopenharmony_ci					else
275f08c3bdfSopenharmony_ci						tst_brkm(TBROK | TERRNO, getout,
276f08c3bdfSopenharmony_ci							 "kill(%d, %d) failed, but kill(%d, SIGTERM) worked",
277f08c3bdfSopenharmony_ci							 pid, sig, pid);
278f08c3bdfSopenharmony_ci				} else
279f08c3bdfSopenharmony_ci					tst_brkm(TBROK | TERRNO, getout,
280f08c3bdfSopenharmony_ci						 "kill(%d, %d) failed", pid,
281f08c3bdfSopenharmony_ci						 sig);
282f08c3bdfSopenharmony_ci			}
283f08c3bdfSopenharmony_ci		}
284f08c3bdfSopenharmony_ci	}
285f08c3bdfSopenharmony_ci
286f08c3bdfSopenharmony_ci	if (write_pipe(pipe_fd2[1], READY) < 0) {
287f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, getout,
288f08c3bdfSopenharmony_ci			 "Unable to tell child to go, write to pipe failed");
289f08c3bdfSopenharmony_ci	}
290f08c3bdfSopenharmony_ci
291f08c3bdfSopenharmony_ci	/*
292f08c3bdfSopenharmony_ci	 * child is now releasing signals, wait and check exit value
293f08c3bdfSopenharmony_ci	 */
294f08c3bdfSopenharmony_ci	SAFE_WAIT(getout, &term_stat);
295f08c3bdfSopenharmony_ci
296f08c3bdfSopenharmony_ci	/* check child's signal exit value */
297f08c3bdfSopenharmony_ci	if ((sig = CHILD_SIG(term_stat)) != 0)
298f08c3bdfSopenharmony_ci		/* the child was zapped by a signal */
299f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup, "Unexpected signal %d killed child",
300f08c3bdfSopenharmony_ci			 sig);
301f08c3bdfSopenharmony_ci
302f08c3bdfSopenharmony_ci	/* get child exit value */
303f08c3bdfSopenharmony_ci
304f08c3bdfSopenharmony_ci	rv = CHILD_EXIT(term_stat);
305f08c3bdfSopenharmony_ci
306f08c3bdfSopenharmony_ci	switch (rv) {
307f08c3bdfSopenharmony_ci	case EXIT_OK:
308f08c3bdfSopenharmony_ci		/* sig_array sent back on pipe, check it out */
309f08c3bdfSopenharmony_ci		if ((array = (int *)read_pipe(pipe_fd[0])) == NULL) {
310f08c3bdfSopenharmony_ci			/* read_pipe() failed. */
311f08c3bdfSopenharmony_ci			tst_resm(TBROK, "%s", mesg);
312f08c3bdfSopenharmony_ci			break;
313f08c3bdfSopenharmony_ci		}
314f08c3bdfSopenharmony_ci#if DEBUG > 1
315f08c3bdfSopenharmony_ci		for (sig = 1; sig < NUMSIGS; sig++) {
316f08c3bdfSopenharmony_ci			printf("array[%d] = %d\n", sig, array[sig]);
317f08c3bdfSopenharmony_ci		}
318f08c3bdfSopenharmony_ci#endif
319f08c3bdfSopenharmony_ci		caught_sigs = 0;
320f08c3bdfSopenharmony_ci		for (sig = 1; sig < NUMSIGS; sig++) {
321f08c3bdfSopenharmony_ci			if (choose_sig(sig)) {
322f08c3bdfSopenharmony_ci				if (array[sig] != 1) {
323f08c3bdfSopenharmony_ci					/* sig was not caught or caught too many times */
324f08c3bdfSopenharmony_ci					(void)sprintf(mesg,
325f08c3bdfSopenharmony_ci						      "\tsignal %d caught %d times (expected 1).\n",
326f08c3bdfSopenharmony_ci						      sig, array[sig]);
327f08c3bdfSopenharmony_ci					(void)strcat(big_mesg, mesg);
328f08c3bdfSopenharmony_ci					fail = TRUE;
329f08c3bdfSopenharmony_ci				} else {
330f08c3bdfSopenharmony_ci					caught_sigs++;
331f08c3bdfSopenharmony_ci				}
332f08c3bdfSopenharmony_ci			}
333f08c3bdfSopenharmony_ci		}		/* endfor */
334f08c3bdfSopenharmony_ci
335f08c3bdfSopenharmony_ci		if (fail == TRUE)
336f08c3bdfSopenharmony_ci			tst_resm(TFAIL, "%s", big_mesg);
337f08c3bdfSopenharmony_ci		else
338f08c3bdfSopenharmony_ci			tst_resm(TPASS,
339f08c3bdfSopenharmony_ci				 "sigrelse() released all %d signals under test.",
340f08c3bdfSopenharmony_ci				 caught_sigs);
341f08c3bdfSopenharmony_ci		break;
342f08c3bdfSopenharmony_ci
343f08c3bdfSopenharmony_ci	case TBROK:
344f08c3bdfSopenharmony_ci		/* get BROK message from pipe */
345f08c3bdfSopenharmony_ci		if ((str = read_pipe(pipe_fd[0])) == NULL) {
346f08c3bdfSopenharmony_ci			/* read_pipe() failed. */
347f08c3bdfSopenharmony_ci			tst_resm(TBROK, "%s", mesg);
348f08c3bdfSopenharmony_ci			break;
349f08c3bdfSopenharmony_ci		}
350f08c3bdfSopenharmony_ci
351f08c3bdfSopenharmony_ci		/* call tst_res: str contains the message */
352f08c3bdfSopenharmony_ci		tst_resm(TBROK, "%s", str);
353f08c3bdfSopenharmony_ci		break;
354f08c3bdfSopenharmony_ci	case SIG_CAUGHT:
355f08c3bdfSopenharmony_ci		/* a signal was caught before it was released */
356f08c3bdfSopenharmony_ci		tst_resm(TBROK, "A signal was caught before being released.");
357f08c3bdfSopenharmony_ci		break;
358f08c3bdfSopenharmony_ci	case WRITE_BROK:
359f08c3bdfSopenharmony_ci		/* the write() call failed in child's write_pipe */
360f08c3bdfSopenharmony_ci		tst_resm(TBROK, "write() pipe failed for child.");
361f08c3bdfSopenharmony_ci		break;
362f08c3bdfSopenharmony_ci	case HANDLE_ERR:
363f08c3bdfSopenharmony_ci		/* more than one signal tried to be handled at the same time */
364f08c3bdfSopenharmony_ci		tst_resm(TBROK, "Error occured in signal handler.");
365f08c3bdfSopenharmony_ci		break;
366f08c3bdfSopenharmony_ci	default:
367f08c3bdfSopenharmony_ci		tst_resm(TBROK, "Unexpected exit code %d from child", rv);
368f08c3bdfSopenharmony_ci		break;
369f08c3bdfSopenharmony_ci	}
370f08c3bdfSopenharmony_ci
371f08c3bdfSopenharmony_ci}				/* end of parent */
372f08c3bdfSopenharmony_ci
373f08c3bdfSopenharmony_ci/****************************************************************************
374f08c3bdfSopenharmony_ci * child() : hold signals, notify parent and wait for parent to send signals.
375f08c3bdfSopenharmony_ci *   If none were caught (sighold worked), release the signals one at a time
376f08c3bdfSopenharmony_ci *   and wait for them to be caught.  Send results back to parent
377f08c3bdfSopenharmony_ci *   for processing.
378f08c3bdfSopenharmony_ci ***************************************************************************/
379f08c3bdfSopenharmony_cistatic void child(void)
380f08c3bdfSopenharmony_ci{
381f08c3bdfSopenharmony_ci	int rv;			/* return value from sighold() and sigrelse() */
382f08c3bdfSopenharmony_ci	int sig;		/* signal value */
383f08c3bdfSopenharmony_ci	int exit_val;		/* exit value to send to parent */
384f08c3bdfSopenharmony_ci	char note[MAXMESG];	/* message buffer for pipe */
385f08c3bdfSopenharmony_ci	char *str;
386f08c3bdfSopenharmony_ci
387f08c3bdfSopenharmony_ci	phase = 1;		/* tell handler that we do not want to catch signals */
388f08c3bdfSopenharmony_ci
389f08c3bdfSopenharmony_ci	/* set note to READY and if an error occurs, overwrite it */
390f08c3bdfSopenharmony_ci	(void)strcpy(note, READY);
391f08c3bdfSopenharmony_ci
392f08c3bdfSopenharmony_ci	/* set alarm in case something hangs */
393f08c3bdfSopenharmony_ci	if (set_timeout() < 0) {
394f08c3bdfSopenharmony_ci		/* an error occured - put mesg in note and send it back to parent */
395f08c3bdfSopenharmony_ci		(void)strcpy(note, mesg);
396f08c3bdfSopenharmony_ci
397f08c3bdfSopenharmony_ci	} else if (setup_sigs() < 0) {
398f08c3bdfSopenharmony_ci		/* an error occured - put mesg in note and send it back to parent */
399f08c3bdfSopenharmony_ci		(void)strcpy(note, mesg);
400f08c3bdfSopenharmony_ci
401f08c3bdfSopenharmony_ci	} else {
402f08c3bdfSopenharmony_ci		/* all set up to catch signals, now hold them */
403f08c3bdfSopenharmony_ci
404f08c3bdfSopenharmony_ci		for (sig = 1; sig < NUMSIGS; sig++) {
405f08c3bdfSopenharmony_ci			if (choose_sig(sig)) {
406f08c3bdfSopenharmony_ci				if ((rv = sighold(sig)) != 0) {
407f08c3bdfSopenharmony_ci					/* THEY say sighold ALWAYS returns 0 */
408f08c3bdfSopenharmony_ci					(void)sprintf(note,
409f08c3bdfSopenharmony_ci						      "sighold did not return 0. rv:%d",
410f08c3bdfSopenharmony_ci						      rv);
411f08c3bdfSopenharmony_ci					break;
412f08c3bdfSopenharmony_ci				}
413f08c3bdfSopenharmony_ci			}
414f08c3bdfSopenharmony_ci		}
415f08c3bdfSopenharmony_ci
416f08c3bdfSopenharmony_ci	}
417f08c3bdfSopenharmony_ci
418f08c3bdfSopenharmony_ci	/*
419f08c3bdfSopenharmony_ci	 * send note to parent (if not READY, parent will BROK) and
420f08c3bdfSopenharmony_ci	 * wait for parent to send signals.  The timeout clock is set so
421f08c3bdfSopenharmony_ci	 * that we will not wait forever - if sighold() did its job, we
422f08c3bdfSopenharmony_ci	 * will not receive the signals.  If sighold() blew it we will
423f08c3bdfSopenharmony_ci	 * catch a signal and the interrupt handler will exit with a
424f08c3bdfSopenharmony_ci	 * value of SIG_CAUGHT.
425f08c3bdfSopenharmony_ci	 */
426f08c3bdfSopenharmony_ci	if (write_pipe(pipe_fd[1], note) < 0) {
427f08c3bdfSopenharmony_ci		/*
428f08c3bdfSopenharmony_ci		 * write_pipe() failed.  Set exit value to WRITE_BROK to let
429f08c3bdfSopenharmony_ci		 * parent know what happened
430f08c3bdfSopenharmony_ci		 */
431f08c3bdfSopenharmony_ci		clear_timeout();
432f08c3bdfSopenharmony_ci		exit(WRITE_BROK);
433f08c3bdfSopenharmony_ci	}
434f08c3bdfSopenharmony_ci
435f08c3bdfSopenharmony_ci	/*
436f08c3bdfSopenharmony_ci	 * if we get to this point, all signals have been held and the
437f08c3bdfSopenharmony_ci	 * timer has expired.  Now what we want to do is release each
438f08c3bdfSopenharmony_ci	 * signal and see if we catch it.  If we catch all signals,
439f08c3bdfSopenharmony_ci	 * sigrelse passed, else it failed.
440f08c3bdfSopenharmony_ci	 */
441f08c3bdfSopenharmony_ci
442f08c3bdfSopenharmony_ci	phase = 2;		/* let handler know we are now expecting signals */
443f08c3bdfSopenharmony_ci
444f08c3bdfSopenharmony_ci#if DEBUG > 0
445f08c3bdfSopenharmony_ci	printf("child: PHASE II\n");
446f08c3bdfSopenharmony_ci#endif
447f08c3bdfSopenharmony_ci
448f08c3bdfSopenharmony_ci	/* assume success and overwrite exit_val if an error occurs */
449f08c3bdfSopenharmony_ci	exit_val = EXIT_OK;
450f08c3bdfSopenharmony_ci
451f08c3bdfSopenharmony_ci#if DEBUG > 0
452f08c3bdfSopenharmony_ci	printf("child: pid=%d waiting for parent's ready...\n", getpid());
453f08c3bdfSopenharmony_ci#endif
454f08c3bdfSopenharmony_ci
455f08c3bdfSopenharmony_ci	/*
456f08c3bdfSopenharmony_ci	 * wait for parent to tell us that sigals were all sent
457f08c3bdfSopenharmony_ci	 */
458f08c3bdfSopenharmony_ci
459f08c3bdfSopenharmony_ci	/* wait for "ready" message from parent */
460f08c3bdfSopenharmony_ci	if ((str = read_pipe(pipe_fd2[0])) == NULL) {
461f08c3bdfSopenharmony_ci		/* read_pipe() failed. */
462f08c3bdfSopenharmony_ci		printf(" child: read_pipe failed\n");
463f08c3bdfSopenharmony_ci		exit(TBROK);
464f08c3bdfSopenharmony_ci	}
465f08c3bdfSopenharmony_ci
466f08c3bdfSopenharmony_ci	if (strcmp(str, READY) != 0) {
467f08c3bdfSopenharmony_ci		/* parent/pipe problem */
468f08c3bdfSopenharmony_ci		printf("child: didn't proper ready message\n");
469f08c3bdfSopenharmony_ci		exit(TBROK);
470f08c3bdfSopenharmony_ci	}
471f08c3bdfSopenharmony_ci
472f08c3bdfSopenharmony_ci	for (sig = 1; sig < NUMSIGS; sig++) {
473f08c3bdfSopenharmony_ci		if (choose_sig(sig)) {
474f08c3bdfSopenharmony_ci
475f08c3bdfSopenharmony_ci			/* all set up, release and catch a signal */
476f08c3bdfSopenharmony_ci
477f08c3bdfSopenharmony_ci			sig_caught = FALSE;	/* handler sets it to TRUE when caught */
478f08c3bdfSopenharmony_ci#if DEBUG > 1
479f08c3bdfSopenharmony_ci			printf("child: releasing sig %d...\n", sig);
480f08c3bdfSopenharmony_ci#endif
481f08c3bdfSopenharmony_ci			if ((rv = sigrelse(sig)) != 0) {
482f08c3bdfSopenharmony_ci				/* THEY say sigrelse ALWAYS returns 0 */
483f08c3bdfSopenharmony_ci				(void)sprintf(note,
484f08c3bdfSopenharmony_ci					      "sigrelse did not return 0. rv:%d",
485f08c3bdfSopenharmony_ci					      rv);
486f08c3bdfSopenharmony_ci				exit_val = TBROK;
487f08c3bdfSopenharmony_ci				break;
488f08c3bdfSopenharmony_ci			}
489f08c3bdfSopenharmony_ci
490f08c3bdfSopenharmony_ci			/* give signal handler some time to process signal */
491f08c3bdfSopenharmony_ci			wait_a_while();
492f08c3bdfSopenharmony_ci		}
493f08c3bdfSopenharmony_ci
494f08c3bdfSopenharmony_ci	}			/* endfor */
495f08c3bdfSopenharmony_ci
496f08c3bdfSopenharmony_ci	/*
497f08c3bdfSopenharmony_ci	 * If we are error free so far...
498f08c3bdfSopenharmony_ci	 * check the sig_array array for one occurence of
499f08c3bdfSopenharmony_ci	 * each of the catchable signals.  If this is true,
500f08c3bdfSopenharmony_ci	 * then PASS, otherwise FAIL.
501f08c3bdfSopenharmony_ci	 */
502f08c3bdfSopenharmony_ci
503f08c3bdfSopenharmony_ci	if (exit_val == EXIT_OK) {
504f08c3bdfSopenharmony_ci		(void)memcpy(note, (char *)sig_array, sizeof(sig_array));
505f08c3bdfSopenharmony_ci	}
506f08c3bdfSopenharmony_ci
507f08c3bdfSopenharmony_ci	/* send note to parent and exit */
508f08c3bdfSopenharmony_ci	if (write_pipe(pipe_fd[1], note) < 0) {
509f08c3bdfSopenharmony_ci		/*
510f08c3bdfSopenharmony_ci		 * write_pipe() failed.  Set exit value to WRITE_BROK to let
511f08c3bdfSopenharmony_ci		 * parent know what happened
512f08c3bdfSopenharmony_ci		 */
513f08c3bdfSopenharmony_ci		exit(WRITE_BROK);
514f08c3bdfSopenharmony_ci	}
515f08c3bdfSopenharmony_ci
516f08c3bdfSopenharmony_ci	exit(exit_val);
517f08c3bdfSopenharmony_ci
518f08c3bdfSopenharmony_ci}				/* end of child */
519f08c3bdfSopenharmony_ci
520f08c3bdfSopenharmony_ci/*****************************************************************************
521f08c3bdfSopenharmony_ci *  setup_sigs() : set child up to catch all signals.  If there is
522f08c3bdfSopenharmony_ci *       trouble, write message in mesg and return -1, else return 0.
523f08c3bdfSopenharmony_ci *       The signal handler has two functions depending on which phase
524f08c3bdfSopenharmony_ci *       of the test we are in.  The first section is executed after the
525f08c3bdfSopenharmony_ci *       signals have been held (should not ever be used).  The second
526f08c3bdfSopenharmony_ci *       section is executed after the signals have been released (should
527f08c3bdfSopenharmony_ci *       be executed for each signal).
528f08c3bdfSopenharmony_ci ****************************************************************************/
529f08c3bdfSopenharmony_cistatic int setup_sigs(void)
530f08c3bdfSopenharmony_ci{
531f08c3bdfSopenharmony_ci	int sig;
532f08c3bdfSopenharmony_ci
533f08c3bdfSopenharmony_ci	/* set up signal handler routine */
534f08c3bdfSopenharmony_ci	for (sig = 1; sig < NUMSIGS; sig++) {
535f08c3bdfSopenharmony_ci		if (choose_sig(sig)) {
536f08c3bdfSopenharmony_ci			if (signal(sig, handler) == SIG_ERR) {
537f08c3bdfSopenharmony_ci				/* set up mesg to send back to parent */
538f08c3bdfSopenharmony_ci				(void)sprintf(mesg,
539f08c3bdfSopenharmony_ci					      "signal() failed for signal %d. error:%d %s.",
540f08c3bdfSopenharmony_ci					      sig, errno, strerror(errno));
541f08c3bdfSopenharmony_ci				return (-1);
542f08c3bdfSopenharmony_ci			}
543f08c3bdfSopenharmony_ci		}
544f08c3bdfSopenharmony_ci	}
545f08c3bdfSopenharmony_ci	return 0;
546f08c3bdfSopenharmony_ci
547f08c3bdfSopenharmony_ci}				/* end of setup_sigs  */
548f08c3bdfSopenharmony_ci
549f08c3bdfSopenharmony_ci/*****************************************************************************
550f08c3bdfSopenharmony_ci *  handler() : child's interrupt handler for all signals.  The phase variable
551f08c3bdfSopenharmony_ci *      is set in the child process indicating what action is to be taken.
552f08c3bdfSopenharmony_ci *    The phase 1 section will be run if the child process catches a signal
553f08c3bdfSopenharmony_ci *      after the signal has been held resulting in a test item BROK.
554f08c3bdfSopenharmony_ci *      The parent detects this situation by a child exit value of SIG_CAUGHT.
555f08c3bdfSopenharmony_ci *    The phase 2 section will be run if the child process catches a
556f08c3bdfSopenharmony_ci *      signal after the signal has been released.  All signals must be
557f08c3bdfSopenharmony_ci *      caught in order for a PASS.
558f08c3bdfSopenharmony_ci ****************************************************************************/
559f08c3bdfSopenharmony_cistatic void handler(int sig)
560f08c3bdfSopenharmony_ci{
561f08c3bdfSopenharmony_ci	static int s = 0;	/* semaphore so that we don't handle 2 */
562f08c3bdfSopenharmony_ci	/* sigs at once */
563f08c3bdfSopenharmony_ci#if DEBUG > 1
564f08c3bdfSopenharmony_ci	printf("child: handler phase%d: caught signal %d.\n", phase, sig);
565f08c3bdfSopenharmony_ci#endif
566f08c3bdfSopenharmony_ci
567f08c3bdfSopenharmony_ci	if (phase == 1) {
568f08c3bdfSopenharmony_ci		/* exit the child process with a value of -1 */
569f08c3bdfSopenharmony_ci		exit(SIG_CAUGHT);
570f08c3bdfSopenharmony_ci
571f08c3bdfSopenharmony_ci	} else {
572f08c3bdfSopenharmony_ci		/* phase 2 (error if s gets incremented twice) */
573f08c3bdfSopenharmony_ci		++s;
574f08c3bdfSopenharmony_ci
575f08c3bdfSopenharmony_ci		if (s > 1) {
576f08c3bdfSopenharmony_ci			exit(HANDLE_ERR);
577f08c3bdfSopenharmony_ci		}
578f08c3bdfSopenharmony_ci
579f08c3bdfSopenharmony_ci		/* increment the array element for this signal */
580f08c3bdfSopenharmony_ci		++sig_array[sig];
581f08c3bdfSopenharmony_ci		sig_caught = TRUE;	/* flag for wait_a_while () */
582f08c3bdfSopenharmony_ci		--s;
583f08c3bdfSopenharmony_ci	}
584f08c3bdfSopenharmony_ci
585f08c3bdfSopenharmony_ci	return;
586f08c3bdfSopenharmony_ci
587f08c3bdfSopenharmony_ci}				/* end of handler */
588f08c3bdfSopenharmony_ci
589f08c3bdfSopenharmony_ci/*****************************************************************************
590f08c3bdfSopenharmony_ci *  read_pipe() : read data from pipe and return in buf.  If an error occurs
591f08c3bdfSopenharmony_ci *      put message in mesg and return NULL.  Note: this routine sets a
592f08c3bdfSopenharmony_ci *      timeout signal in case the pipe is blocked.
593f08c3bdfSopenharmony_ci ****************************************************************************/
594f08c3bdfSopenharmony_cistatic char *read_pipe(int fd)
595f08c3bdfSopenharmony_ci{
596f08c3bdfSopenharmony_ci	static char buf[MAXMESG];	/* buffer for pipe read */
597f08c3bdfSopenharmony_ci	int ret;
598f08c3bdfSopenharmony_ci
599f08c3bdfSopenharmony_ci#if DEBUG > 0
600f08c3bdfSopenharmony_ci	printf("read_pipe: pid=%d waiting...\n", getpid());
601f08c3bdfSopenharmony_ci#endif
602f08c3bdfSopenharmony_ci
603f08c3bdfSopenharmony_ci	/* set timeout alarm in case the pipe is blocked */
604f08c3bdfSopenharmony_ci	if (set_timeout() < 0) {
605f08c3bdfSopenharmony_ci		/* an error occured, message in mesg */
606f08c3bdfSopenharmony_ci		return NULL;
607f08c3bdfSopenharmony_ci	}
608f08c3bdfSopenharmony_ci
609f08c3bdfSopenharmony_ci	ret = -1;
610f08c3bdfSopenharmony_ci	while (ret == -1) {	/* while empty reads */
611f08c3bdfSopenharmony_ci		if ((ret = read(fd, buf, MAXMESG)) == 0) {
612f08c3bdfSopenharmony_ci			(void)sprintf(mesg, "read() pipe failed. error:%d %s.",
613f08c3bdfSopenharmony_ci				      errno, strerror(errno));
614f08c3bdfSopenharmony_ci
615f08c3bdfSopenharmony_ci			clear_timeout();
616f08c3bdfSopenharmony_ci			return NULL;
617f08c3bdfSopenharmony_ci		}
618f08c3bdfSopenharmony_ci	}
619f08c3bdfSopenharmony_ci	clear_timeout();
620f08c3bdfSopenharmony_ci
621f08c3bdfSopenharmony_ci#if DEBUG > 0
622f08c3bdfSopenharmony_ci	printf("read_pipe: pid=%d received: %s.\n", getpid(), buf);
623f08c3bdfSopenharmony_ci#endif
624f08c3bdfSopenharmony_ci	return (buf);
625f08c3bdfSopenharmony_ci
626f08c3bdfSopenharmony_ci}				/* end of read_pipe */
627f08c3bdfSopenharmony_ci
628f08c3bdfSopenharmony_ci/*****************************************************************************
629f08c3bdfSopenharmony_ci *  write_pipe(msg) : write msg to pipe.  If it fails, put message in
630f08c3bdfSopenharmony_ci *       mesg and return -1, else return 0.
631f08c3bdfSopenharmony_ci ****************************************************************************/
632f08c3bdfSopenharmony_cistatic int write_pipe(int fd, char *msg)
633f08c3bdfSopenharmony_ci{
634f08c3bdfSopenharmony_ci
635f08c3bdfSopenharmony_ci#if DEBUG > 0
636f08c3bdfSopenharmony_ci	printf("write_pipe: pid=%d, sending %s.\n", getpid(), msg);
637f08c3bdfSopenharmony_ci#endif
638f08c3bdfSopenharmony_ci
639f08c3bdfSopenharmony_ci	if (write(fd, msg, MAXMESG) < 0) {
640f08c3bdfSopenharmony_ci		(void)sprintf(mesg, "write() pipe failed. error:%d %s.",
641f08c3bdfSopenharmony_ci			      errno, strerror(errno));
642f08c3bdfSopenharmony_ci
643f08c3bdfSopenharmony_ci		return (-1);
644f08c3bdfSopenharmony_ci	}
645f08c3bdfSopenharmony_ci	return 0;
646f08c3bdfSopenharmony_ci
647f08c3bdfSopenharmony_ci}				/* end of write_pipe */
648f08c3bdfSopenharmony_ci
649f08c3bdfSopenharmony_ci/*****************************************************************************
650f08c3bdfSopenharmony_ci *  set_timeout() : set alarm to signal process after the period of time
651f08c3bdfSopenharmony_ci *       indicated by TIMEOUT.  If the signal occurs, the routine timeout()
652f08c3bdfSopenharmony_ci *       will be executed.  If all goes ok, return 0, else load message
653f08c3bdfSopenharmony_ci *       into mesg and return -1.
654f08c3bdfSopenharmony_ci ****************************************************************************/
655f08c3bdfSopenharmony_cistatic int set_timeout(void)
656f08c3bdfSopenharmony_ci{
657f08c3bdfSopenharmony_ci	if (signal(SIGALRM, timeout) == SIG_ERR) {
658f08c3bdfSopenharmony_ci		(void)sprintf(mesg,
659f08c3bdfSopenharmony_ci			      "signal() failed for signal %d. error:%d %s.",
660f08c3bdfSopenharmony_ci			      SIGALRM, errno, strerror(errno));
661f08c3bdfSopenharmony_ci		return (-1);
662f08c3bdfSopenharmony_ci	}
663f08c3bdfSopenharmony_ci
664f08c3bdfSopenharmony_ci	(void)alarm(TIMEOUT);
665f08c3bdfSopenharmony_ci	return 0;
666f08c3bdfSopenharmony_ci
667f08c3bdfSopenharmony_ci}				/* end of set_timeout */
668f08c3bdfSopenharmony_ci
669f08c3bdfSopenharmony_ci/*****************************************************************************
670f08c3bdfSopenharmony_ci *  clear_timeout() : turn off the alarm so that SIGALRM will not get sent.
671f08c3bdfSopenharmony_ci ****************************************************************************/
672f08c3bdfSopenharmony_cistatic void clear_timeout(void)
673f08c3bdfSopenharmony_ci{
674f08c3bdfSopenharmony_ci	(void)alarm(0);
675f08c3bdfSopenharmony_ci
676f08c3bdfSopenharmony_ci}				/* end of clear_timeout */
677f08c3bdfSopenharmony_ci
678f08c3bdfSopenharmony_ci/*****************************************************************************
679f08c3bdfSopenharmony_ci *  timeout() : this routine is executed when the SIGALRM signal is
680f08c3bdfSopenharmony_ci *      caught.  It does nothing but return - the read() on the pipe
681f08c3bdfSopenharmony_ci *      will fail.
682f08c3bdfSopenharmony_ci ****************************************************************************/
683f08c3bdfSopenharmony_cistatic void timeout(int sig)
684f08c3bdfSopenharmony_ci{
685f08c3bdfSopenharmony_ci#if DEBUG > 0
686f08c3bdfSopenharmony_ci	printf("timeout: pid=%d sigalrm caught.\n", getpid());
687f08c3bdfSopenharmony_ci#endif
688f08c3bdfSopenharmony_ci}
689f08c3bdfSopenharmony_ci
690f08c3bdfSopenharmony_ci/*****************************************************************************
691f08c3bdfSopenharmony_ci *  wait_a_while () : wait a while before returning.
692f08c3bdfSopenharmony_ci ****************************************************************************/
693f08c3bdfSopenharmony_cistatic void wait_a_while(void)
694f08c3bdfSopenharmony_ci{
695f08c3bdfSopenharmony_ci	long btime;
696f08c3bdfSopenharmony_ci
697f08c3bdfSopenharmony_ci	btime = time(NULL);
698f08c3bdfSopenharmony_ci	while (time(NULL) - btime < TIMEOUT) {
699f08c3bdfSopenharmony_ci		if (sig_caught == TRUE)
700f08c3bdfSopenharmony_ci			break;
701f08c3bdfSopenharmony_ci	}
702f08c3bdfSopenharmony_ci}				/* end of wait_a_while */
703f08c3bdfSopenharmony_ci
704f08c3bdfSopenharmony_cistatic void getout(void)
705f08c3bdfSopenharmony_ci{
706f08c3bdfSopenharmony_ci	if (pid > 0 && kill(pid, SIGKILL) < 0)
707f08c3bdfSopenharmony_ci		tst_resm(TWARN, "kill(%d, SIGKILL) failed", pid);
708f08c3bdfSopenharmony_ci	cleanup();
709f08c3bdfSopenharmony_ci
710f08c3bdfSopenharmony_ci}				/* end of getout */
711f08c3bdfSopenharmony_ci
712f08c3bdfSopenharmony_ci#ifdef VAX
713f08c3bdfSopenharmony_cistatic int sighold(int signo)
714f08c3bdfSopenharmony_ci{
715f08c3bdfSopenharmony_ci	return 0;
716f08c3bdfSopenharmony_ci}
717f08c3bdfSopenharmony_ci
718f08c3bdfSopenharmony_cistatic int sigrelse(signo)
719f08c3bdfSopenharmony_ciint signo;
720f08c3bdfSopenharmony_ci{
721f08c3bdfSopenharmony_ci	return 0;
722f08c3bdfSopenharmony_ci}
723f08c3bdfSopenharmony_ci#endif
724f08c3bdfSopenharmony_ci
725f08c3bdfSopenharmony_ciint choose_sig(int sig)
726f08c3bdfSopenharmony_ci{
727f08c3bdfSopenharmony_ci	switch (sig) {
728f08c3bdfSopenharmony_ci
729f08c3bdfSopenharmony_ci	case SIGKILL:
730f08c3bdfSopenharmony_ci	case SIGSTOP:
731f08c3bdfSopenharmony_ci	case SIGTSTP:
732f08c3bdfSopenharmony_ci	case SIGCONT:
733f08c3bdfSopenharmony_ci	case SIGALRM:
734f08c3bdfSopenharmony_ci	case SIGCANCEL:
735f08c3bdfSopenharmony_ci	case SIGTIMER:
736f08c3bdfSopenharmony_ci#ifdef SIGNOBDM
737f08c3bdfSopenharmony_ci	case SIGNOBDM:
738f08c3bdfSopenharmony_ci#endif
739f08c3bdfSopenharmony_ci#ifdef SIGTTIN
740f08c3bdfSopenharmony_ci	case SIGTTIN:
741f08c3bdfSopenharmony_ci#endif
742f08c3bdfSopenharmony_ci#ifdef SIGTTOU
743f08c3bdfSopenharmony_ci	case SIGTTOU:
744f08c3bdfSopenharmony_ci#endif
745f08c3bdfSopenharmony_ci#ifdef  SIGPTINTR
746f08c3bdfSopenharmony_ci	case SIGPTINTR:
747f08c3bdfSopenharmony_ci#endif
748f08c3bdfSopenharmony_ci#ifdef  SIGSWAP
749f08c3bdfSopenharmony_ci	case SIGSWAP:
750f08c3bdfSopenharmony_ci#endif
751f08c3bdfSopenharmony_ci		return 0;
752f08c3bdfSopenharmony_ci
753f08c3bdfSopenharmony_ci	}
754f08c3bdfSopenharmony_ci
755f08c3bdfSopenharmony_ci	return 1;
756f08c3bdfSopenharmony_ci
757f08c3bdfSopenharmony_ci}
758f08c3bdfSopenharmony_ci
759f08c3bdfSopenharmony_civoid setup(void)
760f08c3bdfSopenharmony_ci{
761f08c3bdfSopenharmony_ci
762f08c3bdfSopenharmony_ci	tst_sig(FORK, DEF_HANDLER, cleanup);
763f08c3bdfSopenharmony_ci
764f08c3bdfSopenharmony_ci	TEST_PAUSE;
765f08c3bdfSopenharmony_ci
766f08c3bdfSopenharmony_ci	tst_tmpdir();
767f08c3bdfSopenharmony_ci
768f08c3bdfSopenharmony_ci	/* set up pipe for parent/child communications */
769f08c3bdfSopenharmony_ci	SAFE_PIPE(cleanup, pipe_fd);
770f08c3bdfSopenharmony_ci
771f08c3bdfSopenharmony_ci	/*
772f08c3bdfSopenharmony_ci	 * Cause the read to return 0 once EOF is encountered and the
773f08c3bdfSopenharmony_ci	 * read to return -1 if pipe is empty.
774f08c3bdfSopenharmony_ci	 */
775f08c3bdfSopenharmony_ci	if (fcntl(pipe_fd[0], F_SETFL, O_NONBLOCK) == -1)
776f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup,
777f08c3bdfSopenharmony_ci			 "fcntl(Fds[0], F_SETFL, O_NONBLOCK) failed");
778f08c3bdfSopenharmony_ci
779f08c3bdfSopenharmony_ci	/* set up pipe for parent/child communications */
780f08c3bdfSopenharmony_ci	SAFE_PIPE(cleanup, pipe_fd2);
781f08c3bdfSopenharmony_ci
782f08c3bdfSopenharmony_ci	/*
783f08c3bdfSopenharmony_ci	 * Cause the read to return 0 once EOF is encountered and the
784f08c3bdfSopenharmony_ci	 * read to return -1 if pipe is empty.
785f08c3bdfSopenharmony_ci	 */
786f08c3bdfSopenharmony_ci	if (fcntl(pipe_fd2[0], F_SETFL, O_NONBLOCK) == -1)
787f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup,
788f08c3bdfSopenharmony_ci			 "fcntl(Fds[0], F_SETFL, O_NONBLOCK) failed");
789f08c3bdfSopenharmony_ci}
790f08c3bdfSopenharmony_ci
791f08c3bdfSopenharmony_civoid cleanup(void)
792f08c3bdfSopenharmony_ci{
793f08c3bdfSopenharmony_ci	tst_rmdir();
794f08c3bdfSopenharmony_ci
795f08c3bdfSopenharmony_ci}
796