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 20 /* 21 * NAME 22 * pipe09.c 23 * 24 * DESCRIPTION 25 * Check that two processes can use the same pipe at the same time. 26 * 27 * ALGORITHM 28 * 1. Open a pipe 29 * 2. Fork a child which writes to the pipe 30 * 3. Fork another child which writes a different character to the pipe 31 * 4. Have the parent read from the pipe 32 * 5. It should get the characters from both children. 33 * 34 * USAGE: <for command-line> 35 * pipe09 [-c n] [-f] [-i n] [-I x] [-P x] [-t] 36 * where, -c n : Run n copies concurrently. 37 * -f : Turn off functionality Testing. 38 * -i n : Execute test n times. 39 * -I x : Execute test for x seconds. 40 * -P x : Pause for x seconds between iterations. 41 * -t : Turn on syscall timing. 42 * 43 * HISTORY 44 * 07/2001 Ported by Wayne Boyer 45 * 46 * RESTRICTIONS 47 * None 48 */ 49 #include <unistd.h> 50 #include <signal.h> 51 #include <wait.h> 52 #include <errno.h> 53 #include "test.h" 54 55 #define PIPEWRTCNT 100 /* must be an even number */ 56 57 char *TCID = "pipe09"; 58 int TST_TOTAL = 1; 59 60 void setup(void); 61 void cleanup(void); 62 63 ssize_t do_read(int fd, void *buf, size_t count) 64 { 65 ssize_t n; 66 67 do { 68 n = read(fd, buf, count); 69 } while (n < 0 && errno == EINTR); 70 71 return n; 72 } 73 74 int main(int ac, char **av) 75 { 76 int lc; 77 78 int i, red, wtstatus; 79 int pipefd[2]; /* fds for pipe read/write */ 80 char rebuf[BUFSIZ]; 81 int Acnt = 0, Bcnt = 0; /* count 'A' and 'B' */ 82 int fork_1, fork_2; /* ret values in parent */ 83 84 tst_parse_opts(ac, av, NULL, NULL); 85 86 setup(); 87 88 for (lc = 0; TEST_LOOPING(lc); lc++) { 89 90 /* reset tst_count in case we are looping */ 91 tst_count = 0; 92 93 TEST(pipe(pipefd)); 94 95 if (TEST_RETURN == -1) { 96 tst_resm(TFAIL, "pipe() call failed"); 97 continue; 98 } 99 100 if ((fork_1 = FORK_OR_VFORK()) == -1) { 101 tst_brkm(TBROK, cleanup, "fork() #1 failed"); 102 } 103 104 if (fork_1 == 0) { /* 1st child */ 105 if (close(pipefd[0]) != 0) { 106 tst_resm(TWARN, "pipefd[0] close failed, " 107 "errno = %d", errno); 108 exit(1); 109 } 110 111 for (i = 0; i < PIPEWRTCNT / 2; ++i) { 112 if (write(pipefd[1], "A", 1) != 1) { 113 tst_resm(TWARN, "write to pipe failed"); 114 exit(1); 115 } 116 } 117 exit(0); 118 } 119 120 /* parent */ 121 122 if (waitpid(fork_1, &wtstatus, 0) == -1) 123 tst_brkm(TBROK, cleanup, "waitpid failed"); 124 if (WIFEXITED(wtstatus) && WEXITSTATUS(wtstatus) != 0) { 125 tst_brkm(TBROK, cleanup, "child exited abnormally"); 126 } 127 128 if ((fork_2 = FORK_OR_VFORK()) == -1) { 129 tst_brkm(TBROK, cleanup, "fork() #2 failed"); 130 } 131 132 if (fork_2 == 0) { /* 2nd child */ 133 if (close(pipefd[0]) != 0) { 134 perror("pipefd[0] close failed"); 135 exit(1); 136 } 137 138 for (i = 0; i < PIPEWRTCNT / 2; ++i) { 139 if (write(pipefd[1], "B", 1) != 1) { 140 perror("write to pipe failed"); 141 exit(1); 142 } 143 } 144 exit(0); 145 } 146 147 /* parent */ 148 149 if (waitpid(fork_2, &wtstatus, 0) == -1) 150 tst_brkm(TBROK, cleanup, "waitpid failed"); 151 if (WEXITSTATUS(wtstatus) != 0) { 152 tst_brkm(TBROK, cleanup, "problem detected in child, " 153 "wait status %d, errno = %d", wtstatus, errno); 154 } 155 156 if (close(pipefd[1]) != 0) { 157 tst_brkm(TBROK | TERRNO, cleanup, 158 "pipefd[1] close failed"); 159 } 160 161 while ((red = do_read(pipefd[0], rebuf, 100)) > 0) { 162 for (i = 0; i < red; i++) { 163 if (rebuf[i] == 'A') { 164 Acnt++; 165 continue; 166 } 167 if (rebuf[i] == 'B') { 168 Bcnt++; 169 continue; 170 } 171 tst_resm(TFAIL, "got bogus '%c' character", 172 rebuf[i]); 173 break; 174 } 175 } 176 177 if (red == -1) { 178 tst_brkm(TBROK | TERRNO, cleanup, 179 "reading pipefd pipe failed"); 180 } 181 182 if (Bcnt == Acnt && Bcnt == (PIPEWRTCNT / 2)) { 183 tst_resm(TPASS, "functionality appears to be correct"); 184 } else { 185 tst_resm(TFAIL, "functionality is not correct - Acnt " 186 "= %d, Bcnt = %d", Acnt, Bcnt); 187 } 188 189 /* clean up things in case we are looping */ 190 Acnt = Bcnt = 0; 191 } 192 cleanup(); 193 194 tst_exit(); 195 } 196 197 /* 198 * setup() - performs all ONE TIME setup for this test. 199 */ 200 void setup(void) 201 { 202 203 tst_sig(FORK, DEF_HANDLER, cleanup); 204 205 TEST_PAUSE; 206 } 207 208 /* 209 * cleanup() - performs all ONE TIME cleanup for this test at 210 * completion or premature exit. 211 */ 212 void cleanup(void) 213 { 214 } 215