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
99static void setup();
100static void cleanup();
101
102#define LINE_SZ	20
103#define FILENAME "childpid"
104
105char *TCID = "fork01";
106int TST_TOTAL = 2;
107
108/*
109 * child_pid - the child side of the test
110 *             determine the PID and write to a file
111 */
112static 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 */
130static 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
163int 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
219static void setup(void)
220{
221
222	tst_sig(FORK, DEF_HANDLER, cleanup);
223
224	TEST_PAUSE;
225
226	tst_tmpdir();
227}
228
229static void cleanup(void)
230{
231
232	tst_rmdir();
233
234}
235