1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 * 19 * NAME 20 * fork07.c 21 * 22 * DESCRIPTION 23 * Check that all children inherit parent's file descriptor 24 * 25 * ALGORITHM 26 * Parent opens a file, writes to it; forks Nforks children. 27 * Each child attempts to read the file then returns. 28 * Parent reports PASS if all children succeed. 29 * 30 * USAGE 31 * fork07 32 * 33 * HISTORY 34 * 07/2001 Ported by Wayne Boyer 35 * 07/2002 Limited forking and split "infinite forks" test case to 36 * fork12.c by Nate Straz 37 * 38 * RESTRICTIONS 39 * None 40 */ 41 42 #include <stdio.h> 43 #include <errno.h> 44 #include <string.h> 45 #include <sys/wait.h> 46 #include <sys/types.h> 47 #include <sys/stat.h> 48 #include "test.h" 49 50 char *TCID = "fork07"; 51 int TST_TOTAL = 1; 52 53 static void help(void); 54 static void setup(void); 55 static void cleanup(void); 56 57 static char pbuf[10]; 58 static char fnamebuf[40]; 59 60 static char *Nforkarg; 61 static int Nflag; 62 static int Nforks; 63 static int vflag; 64 65 static option_t options[] = { 66 {"N:", &Nflag, &Nforkarg}, 67 {"v", &vflag, NULL}, 68 {NULL, NULL, NULL} 69 }; 70 71 int main(int ac, char **av) 72 { 73 int status, forks, pid1; 74 int ch_r_stat; 75 FILE *rea, *writ; 76 int c_pass, c_fail; 77 78 int lc; 79 80 rea = NULL; 81 writ = NULL; 82 83 tst_parse_opts(ac, av, options, &help); 84 85 if (Nflag) { 86 if (sscanf(Nforkarg, "%i", &Nforks) != 1) 87 tst_brkm(TBROK, cleanup, 88 "--N option arg is not a number"); 89 } else 90 Nforks = 100; 91 92 setup(); 93 94 for (lc = 0; TEST_LOOPING(lc); lc++) { 95 tst_count = 0; 96 97 writ = fopen(fnamebuf, "w"); 98 if (writ == NULL) 99 tst_resm(TFAIL | TERRNO, "fopen(.. \"w\") failed"); 100 rea = fopen(fnamebuf, "r"); 101 if (rea == NULL) 102 tst_resm(TFAIL | TERRNO, "fopen(.. \"r\") failed"); 103 104 fprintf(writ, "abcdefghijklmnopqrstuv"); 105 fflush(writ); 106 sleep(1); 107 108 if ((getc(rea)) != 'a') 109 tst_resm(TFAIL, "getc from read side was confused"); 110 111 /* fork off the children */ 112 tst_resm(TINFO, "Forking %d children", Nforks); 113 tst_flush(); 114 for (forks = 0; forks < Nforks; forks++) { 115 pid1 = fork(); 116 if (pid1 == 0) { 117 ch_r_stat = getc(rea); 118 #ifdef DEBUG 119 tst_resm(TINFO, "Child got char: %c", 120 ch_r_stat); 121 tst_resm(TINFO, 122 "integer value of getc in child " 123 "expected %d got %d", 'b', ch_r_stat); 124 #endif 125 if (ch_r_stat == 'b') { 126 if (vflag) { 127 tst_resm(TINFO, 128 "%6d: read correct character", 129 getpid()); 130 } 131 exit(0); 132 } else { 133 if (vflag) { 134 tst_resm(TINFO, 135 "%6d: read '%c' instead of 'b'", 136 getpid(), 137 (char)ch_r_stat); 138 } 139 exit(1); 140 } 141 } else if (pid1 == -1) 142 tst_brkm(TBROK | TERRNO, cleanup, 143 "fork failed"); 144 } 145 tst_resm(TINFO, "Forked all %d children, now collecting", 146 Nforks); 147 148 /* Collect all the kids and see how they did */ 149 150 c_pass = c_fail = 0; 151 while (wait(&status) > 0) { 152 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 153 c_pass++; 154 else 155 c_fail++; 156 --forks; 157 } 158 if (forks == 0) { 159 tst_resm(TINFO, "Collected all %d children", Nforks); 160 if (c_fail > 0) 161 tst_resm(TFAIL, 162 "%d/%d children didn't read correctly from an inheritted fd", 163 c_fail, Nforks); 164 else 165 tst_resm(TPASS, 166 "%d/%d children read correctly from an inheritted fd", 167 c_pass, Nforks); 168 } else if (forks > 0) 169 tst_brkm(TBROK, cleanup, 170 "There should be %d more children to collect!", 171 forks); 172 else 173 174 tst_brkm(TBROK, cleanup, 175 "Collected %d more children then I should have!", 176 abs(forks)); 177 } 178 fclose(writ); 179 fclose(rea); 180 cleanup(); 181 182 tst_exit(); 183 } 184 185 static void help(void) 186 { 187 printf(" -N n Create n children each iteration\n"); 188 printf(" -v Verbose mode\n"); 189 } 190 191 static void setup(void) 192 { 193 tst_sig(FORK, DEF_HANDLER, cleanup); 194 umask(0); 195 TEST_PAUSE; 196 tst_tmpdir(); 197 198 strcpy(fnamebuf, "fork07."); 199 sprintf(pbuf, "%d", getpid()); 200 strcat(fnamebuf, pbuf); 201 } 202 203 static void cleanup(void) 204 { 205 int waitstatus; 206 207 /* collect our zombies */ 208 while (wait(&waitstatus) > 0) ; 209 210 unlink(fnamebuf); 211 tst_rmdir(); 212 } 213