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