1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 * NAME
19 * fork08.c
20 *
21 * DESCRIPTION
22 * Check if the parent's file descriptors are affected by
23 * actions in the child; they should not be.
24 *
25 * ALGORITHM
26 * Parent opens a file.
27 * Forks a child which closes a file.
28 * Parent forks a second child which attempts to read the (closed)
29 * file.
30 *
31 * USAGE
32 * fork08
33 *
34 * HISTORY
35 * 07/2001 Ported by Wayne Boyer
36 *
37 * RESTRICTIONS
38 * None
39 */
40
41 #include <sys/types.h>
42 #include <sys/wait.h>
43 #include <sys/stat.h>
44 #include <stdio.h>
45 #include "test.h"
46
47 char *TCID = "fork08";
48 int TST_TOTAL = 1;
49
50 static void setup(void);
51 static void cleanup(void);
52
53 static char pbuf[10];
54 static char fnamebuf[40];
55
main(int ac,char ** av)56 int main(int ac, char **av)
57 {
58 int status, count, forks, pid1;
59 int ch_r_stat;
60 FILE *rea, *writ;
61
62 int lc;
63
64 tst_parse_opts(ac, av, NULL, NULL);
65
66 setup();
67
68 for (lc = 0; TEST_LOOPING(lc); lc++) {
69 tst_count = 0;
70
71 writ = fopen(fnamebuf, "w");
72 if (writ == NULL)
73 tst_resm(TFAIL, "failed to fopen file for write");
74 rea = fopen(fnamebuf, "r");
75 if (rea == NULL)
76 tst_resm(TFAIL, "failed to fopen file for read");
77
78 fprintf(writ, "abcdefghijklmnopqrstuv");
79 fflush(writ);
80 sleep(1);
81
82 if ((getc(rea)) != 'a')
83 tst_resm(TFAIL, "getc from read side was confused");
84
85 forks = 0;
86
87 forkone:
88 ++forks;
89
90 pid1 = fork();
91 if (pid1 != 0) {
92 tst_resm(TINFO, "parent forksval: %d", forks);
93
94 if ((pid1 != (-1)) && (forks < 2))
95 goto forkone;
96 else if (pid1 < 0)
97 tst_resm(TINFO, "Fork failed");
98 } else { /* child */
99 /*
100 * If first child close the file descriptor for the
101 * read stream
102 */
103 if (forks == 1) {
104 if ((fclose(rea)) == -1) {
105 tst_resm(TFAIL, "error in first child"
106 " closing fildes");
107 }
108 _exit(0);
109 }
110
111 /*
112 * If second child attempt to read from the file
113 */
114 else if (forks == 2) {
115 ch_r_stat = getc(rea);
116 tst_resm(TINFO, "second child got char: %c",
117 ch_r_stat);
118 if (ch_r_stat == 'b') {
119 tst_resm(TPASS, "Test passed in child"
120 "number %d", forks);
121 exit(0);
122 } else if (ch_r_stat == EOF) {
123 tst_resm(TFAIL, "Second child got "
124 "EOF");
125 exit(-1);
126 } else {
127 tst_resm(TFAIL, "test failed in child"
128 "no %d", forks);
129 exit(-1);
130 }
131 } else { /* end of second child */
132 tst_resm(TINFO, "forksnumber: %d", forks);
133 exit(3);
134 }
135 }
136
137 for (count = 0; count <= forks; count++) {
138 wait(&status);
139 tst_resm(TINFO, "exit status of wait "
140 " expected 0 got %d", status);
141 status >>= 8;
142 if (status == 0)
143 tst_resm(TPASS, "parent test PASSED");
144 else
145 tst_resm(TFAIL, "parent test FAILED");
146 }
147
148 tst_resm(TINFO, "Number of processes forked is %d", forks);
149 fclose(rea);
150 fclose(writ);
151 }
152
153 cleanup();
154 tst_exit();
155 }
156
setup(void)157 static void setup(void)
158 {
159 tst_sig(FORK, DEF_HANDLER, cleanup);
160 umask(0);
161 TEST_PAUSE;
162 tst_tmpdir();
163
164 strcpy(fnamebuf, "fork07.");
165 sprintf(pbuf, "%d", getpid());
166 strcat(fnamebuf, pbuf);
167 }
168
cleanup(void)169 static void cleanup(void)
170 {
171 tst_rmdir();
172 }
173