Home | History | Annotate | Download | only in fork
      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  *    OS Test - Silicon Graphics, Inc.
     34  *    TEST IDENTIFIER	: fork01
     35  *    EXECUTED BY	: anyone
     36  *    TEST TITLE	: Basic test for fork(2)
     37  *    PARENT DOCUMENT	: frktds02
     38  *    TEST CASE TOTAL	: 2
     39  *    WALL CLOCK TIME	: 1
     40  *    CPU TYPES		: ALL
     41  *    AUTHOR		: Kathy Olmsted
     42  *    CO-PILOT		: Steve Shaw
     43  *    DATE STARTED	: 06/17/92
     44  *    INITIAL RELEASE	: UNICOS 7.0
     45  *    TEST CASES
     46  *	1.) fork returns without error
     47  *	2.) fork returns the pid of the child
     48  *    INPUT SPECIFICATIONS
     49  *	The standard options for system call tests are accepted.
     50  *	(See the parse_opts(3) man page).
     51  *    OUTPUT SPECIFICATIONS
     52  *    DURATION
     53  *	Terminates - with frequency and infinite modes.
     54  *    SIGNALS
     55  *	Uses SIGUSR1 to pause before test if option set.
     56  *	(See the parse_opts(3) man page).
     57  *    RESOURCES
     58  *	None
     59  *    ENVIRONMENTAL NEEDS
     60  *      No run-time environmental needs.
     61  *    SPECIAL PROCEDURAL REQUIREMENTS
     62  *	None
     63  *    INTERCASE DEPENDENCIES
     64  *	None
     65  *    DETAILED DESCRIPTION
     66  *	Setup:
     67  *	Setup signal handling.
     68  *	  Pause for SIGUSR1 if option specified.
     69  *	Test:
     70  *	 Loop if the proper options are given.
     71  *        fork()
     72  *	  Check return code, if system call failed (return=-1)
     73  *		Log the errno and Issue a FAIL message.
     74  *	  Otherwise, Issue a PASS message.
     75  *        CHILD:
     76  *           determine PID
     77  *           write to PID to a file and close the file
     78  *           exit
     79  *        PARENT:
     80  *           wait for child to exit
     81  *           read child PID from file
     82  *           compare child PID to fork() return code and report
     83  *           results
     84  *
     85  *	  Cleanup:
     86  *           Print errno log and/or timing stats if options given
     87  */
     88 
     89 #include <errno.h>
     90 #include <string.h>
     91 #include <signal.h>
     92 #include <fcntl.h>
     93 #include <stdlib.h>
     94 #include <sys/types.h>
     95 #include <sys/wait.h>
     96 #include "test.h"
     97 
     98 #define	KIDEXIT	42
     99 static void setup();
    100 static void cleanup();
    101 
    102 #define LINE_SZ	20
    103 #define FILENAME "childpid"
    104 
    105 char *TCID = "fork01";
    106 int TST_TOTAL = 2;
    107 
    108 /*
    109  * child_pid - the child side of the test
    110  *             determine the PID and write to a file
    111  */
    112 static void child_pid(void)
    113 {
    114 
    115 	int fildes;
    116 	char tmp_line[LINE_SZ];
    117 
    118 	fildes = creat(FILENAME, 0700);
    119 	sprintf(tmp_line, "%d\n", getpid());
    120 	write(fildes, tmp_line, LINE_SZ);
    121 	close(fildes);
    122 
    123 }
    124 
    125 /*
    126  * parent_pid - the parent side of the test
    127  *              read the value determined by the child
    128  *              compare and report results
    129  */
    130 static void parent_pid(void)
    131 {
    132 
    133 	int fildes;
    134 	char tmp_line[LINE_SZ];
    135 	pid_t child_id;
    136 
    137 	fildes = open(FILENAME, O_RDWR);
    138 	if (fildes == -1) {
    139 		tst_brkm(TBROK, cleanup,
    140 			 "parent open failed. errno: %d (%s)\n",
    141 			 errno, strerror(errno));
    142 	} else {
    143 		if (read(fildes, tmp_line, LINE_SZ) == 0) {
    144 			tst_brkm(TBROK, cleanup,
    145 				 "fork(): parent failed to read PID from file errno: %d (%s)",
    146 				 errno, strerror(errno));
    147 		} else {
    148 			child_id = atoi(tmp_line);
    149 			if (TEST_RETURN != child_id) {
    150 				tst_resm(TFAIL,
    151 					 "child reported a pid of %d. parent received %ld from fork()",
    152 					 child_id, TEST_RETURN);
    153 			} else {
    154 				tst_resm(TPASS,
    155 					 "child pid and fork() return agree: %d",
    156 					 child_id);
    157 			}
    158 		}
    159 		close(fildes);
    160 	}
    161 }
    162 
    163 int main(int ac, char **av)
    164 {
    165 	int lc;
    166 	int fails;
    167 	int kid_status, wait_status;
    168 
    169 	tst_parse_opts(ac, av, NULL, NULL);
    170 
    171 	setup();
    172 
    173 	for (lc = 0; TEST_LOOPING(lc); lc++) {
    174 		tst_count = 0;
    175 		fails = 0;
    176 
    177 		TEST(fork());
    178 		if (TEST_RETURN == -1) {
    179 			tst_resm(TFAIL, "fork() Failed, errno=%d : %s",
    180 				 TEST_ERRNO, strerror(TEST_ERRNO));
    181 			tst_resm(TBROK, "unable to continue");
    182 		}
    183 		if (TEST_RETURN == 0) {
    184 			/* child */
    185 			child_pid();
    186 			exit(KIDEXIT);
    187 		} else {
    188 			/* parent */
    189 			tst_resm(TPASS, "fork() returned %ld",
    190 				 TEST_RETURN);
    191 			/* wait for the child to complete */
    192 			wait_status = waitpid(TEST_RETURN, &kid_status, 0);
    193 
    194 			if (wait_status == TEST_RETURN) {
    195 				if (kid_status != KIDEXIT << 8) {
    196 					tst_resm(TBROK,
    197 						 "incorrect child status returned on wait(): %d",
    198 						 kid_status);
    199 					fails++;
    200 				}
    201 			} else {
    202 				tst_resm(TBROK,
    203 					 "wait() for child status failed with %d errno: %d : %s",
    204 					 wait_status, errno,
    205 					 strerror(errno));
    206 				fails++;
    207 			}
    208 			if (fails == 0) {
    209 				/* verification tests */
    210 				parent_pid();
    211 			}
    212 		}		/* TEST_RETURN */
    213 	}
    214 
    215 	cleanup();
    216 	tst_exit();
    217 }
    218 
    219 static void setup(void)
    220 {
    221 
    222 	tst_sig(FORK, DEF_HANDLER, cleanup);
    223 
    224 	TEST_PAUSE;
    225 
    226 	tst_tmpdir();
    227 }
    228 
    229 static void cleanup(void)
    230 {
    231 
    232 	tst_rmdir();
    233 
    234 }
    235