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