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  *
19  * NAME
20  *	fork10.c
21  *
22  * DESCRIPTION
23  *	Check inheritance of file descriptor by children, they
24  *	should all be refering to the same file.
25  *
26  * ALGORITHM
27  *	Child reads several chars and exits.
28  *	Parent forks another child, have the child and parent attempt to use
29  *	that location
30  *
31  * USAGE
32  *	fork10
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 <fcntl.h>
45 #include <stdio.h>
46 #include <errno.h>
47 #include "test.h"
48 #include "safe_macros.h"
49 
50 char *TCID = "fork10";
51 int TST_TOTAL = 1;
52 
53 static void setup(void);
54 static void cleanup(void);
55 
56 static char pidbuf[10];
57 static char fnamebuf[40];
58 
main(int ac,char ** av)59 int main(int ac, char **av)
60 {
61 	int status, pid, fildes;
62 	char parchar[2];
63 	char chilchar[2];
64 
65 	int lc;
66 
67 	fildes = -1;
68 
69 	tst_parse_opts(ac, av, NULL, NULL);
70 
71 	setup();
72 
73 	for (lc = 0; TEST_LOOPING(lc); lc++) {
74 		tst_count = 0;
75 
76 		fildes = SAFE_CREAT(cleanup, fnamebuf, 0600);
77 		write(fildes, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", 27);
78 		close(fildes);
79 
80 		fildes = SAFE_OPEN(cleanup, fnamebuf, 0);
81 
82 		pid = fork();
83 		if (pid == -1)
84 			tst_brkm(TBROK, cleanup, "fork() #1 failed");
85 
86 		if (pid == 0) {	/* child */
87 			tst_resm(TINFO, "fork child A");
88 			if (lseek(fildes, 10L, 0) == -1L) {
89 				tst_resm(TFAIL, "bad lseek by child");
90 				exit(1);
91 			}
92 			exit(0);
93 		} else {	/* parent */
94 			wait(&status);
95 
96 			/* parent starts second child */
97 			pid = fork();
98 			if (pid == -1)
99 				tst_brkm(TBROK, cleanup, "fork() #2 failed");
100 
101 			if (pid == 0) {	/* child */
102 				if (read(fildes, chilchar, 1) <= 0) {
103 					tst_resm(TFAIL, "Child can't read "
104 						 "file");
105 					exit(1);
106 				} else {
107 					if (chilchar[0] != 'K') {
108 						chilchar[1] = '\n';
109 						exit(1);
110 					} else {
111 						exit(0);
112 					}
113 				}
114 			} else {	/* parent */
115 				(void)wait(&status);
116 				if (status >> 8 != 0) {
117 					tst_resm(TFAIL, "Bad return from "
118 						 "second child");
119 					continue;
120 				}
121 				/* parent reads */
122 				if (read(fildes, parchar, 1) <= 0) {
123 					tst_resm(TFAIL, "Parent cannot read "
124 						 "file");
125 					continue;
126 				} else {
127 					write(fildes, parchar, 1);
128 					if (parchar[0] != 'L') {
129 						parchar[1] = '\n';
130 						tst_resm(TFAIL, "Test failed");
131 						continue;
132 					}
133 				}
134 			}
135 		}
136 		tst_resm(TPASS, "test 1 PASSED");
137 	}
138 
139 	close(fildes);
140 	cleanup();
141 	tst_exit();
142 }
143 
setup(void)144 static void setup(void)
145 {
146 	tst_sig(FORK, DEF_HANDLER, cleanup);
147 	umask(0);
148 	TEST_PAUSE;
149 	tst_tmpdir();
150 
151 	strcpy(fnamebuf, "fork10.");
152 	sprintf(pidbuf, "%d", getpid());
153 	strcat(fnamebuf, pidbuf);
154 }
155 
cleanup(void)156 static void cleanup(void)
157 {
158 	tst_rmdir();
159 }
160