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 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 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 169 static void cleanup(void) 170 { 171 tst_rmdir(); 172 } 173