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 */
child_pid(void)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 */
parent_pid(void)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
main(int ac,char ** av)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
setup(void)219 static void setup(void)
220 {
221
222 tst_sig(FORK, DEF_HANDLER, cleanup);
223
224 TEST_PAUSE;
225
226 tst_tmpdir();
227 }
228
cleanup(void)229 static void cleanup(void)
230 {
231
232 tst_rmdir();
233
234 }
235