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 <sys/wait.h> 52 #include <errno.h> 53 #include "test.h" 54 #include "safe_macros.h" 55 56 #define PIPEWRTCNT 100 /* must be an even number */ 57 58 char *TCID = "pipe09"; 59 int TST_TOTAL = 1; 60 61 void setup(void); 62 void cleanup(void); 63 64 ssize_t do_read(int fd, void *buf, size_t count) 65 { 66 ssize_t n; 67 68 do { 69 n = read(fd, buf, count); 70 } while (n < 0 && errno == EINTR); 71 72 return n; 73 } 74 75 int main(int ac, char **av) 76 { 77 int lc; 78 79 int i, red, wtstatus; 80 int pipefd[2]; /* fds for pipe read/write */ 81 char rebuf[BUFSIZ]; 82 int Acnt = 0, Bcnt = 0; /* count 'A' and 'B' */ 83 int fork_1, fork_2; /* ret values in parent */ 84 85 tst_parse_opts(ac, av, NULL, NULL); 86 87 setup(); 88 89 for (lc = 0; TEST_LOOPING(lc); lc++) { 90 91 /* reset tst_count in case we are looping */ 92 tst_count = 0; 93 94 TEST(pipe(pipefd)); 95 96 if (TEST_RETURN == -1) { 97 tst_resm(TFAIL, "pipe() call failed"); 98 continue; 99 } 100 101 if ((fork_1 = FORK_OR_VFORK()) == -1) { 102 tst_brkm(TBROK, cleanup, "fork() #1 failed"); 103 } 104 105 if (fork_1 == 0) { /* 1st child */ 106 if (close(pipefd[0]) != 0) { 107 tst_resm(TWARN, "pipefd[0] close failed, " 108 "errno = %d", errno); 109 exit(1); 110 } 111 112 for (i = 0; i < PIPEWRTCNT / 2; ++i) { 113 if (write(pipefd[1], "A", 1) != 1) { 114 tst_resm(TWARN, "write to pipe failed"); 115 exit(1); 116 } 117 } 118 exit(0); 119 } 120 121 /* parent */ 122 123 SAFE_WAITPID(cleanup, fork_1, &wtstatus, 0); 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 SAFE_WAITPID(cleanup, fork_2, &wtstatus, 0); 150 if (WEXITSTATUS(wtstatus) != 0) { 151 tst_brkm(TBROK, cleanup, "problem detected in child, " 152 "wait status %d, errno = %d", wtstatus, errno); 153 } 154 155 if (close(pipefd[1]) != 0) { 156 tst_brkm(TBROK | TERRNO, cleanup, 157 "pipefd[1] close failed"); 158 } 159 160 while ((red = do_read(pipefd[0], rebuf, 100)) > 0) { 161 for (i = 0; i < red; i++) { 162 if (rebuf[i] == 'A') { 163 Acnt++; 164 continue; 165 } 166 if (rebuf[i] == 'B') { 167 Bcnt++; 168 continue; 169 } 170 tst_resm(TFAIL, "got bogus '%c' character", 171 rebuf[i]); 172 break; 173 } 174 } 175 176 if (red == -1) { 177 tst_brkm(TBROK | TERRNO, cleanup, 178 "reading pipefd pipe failed"); 179 } 180 181 if (Bcnt == Acnt && Bcnt == (PIPEWRTCNT / 2)) { 182 tst_resm(TPASS, "functionality appears to be correct"); 183 } else { 184 tst_resm(TFAIL, "functionality is not correct - Acnt " 185 "= %d, Bcnt = %d", Acnt, Bcnt); 186 } 187 188 /* clean up things in case we are looping */ 189 Acnt = Bcnt = 0; 190 } 191 cleanup(); 192 193 tst_exit(); 194 } 195 196 /* 197 * setup() - performs all ONE TIME setup for this test. 198 */ 199 void setup(void) 200 { 201 202 tst_sig(FORK, DEF_HANDLER, cleanup); 203 204 TEST_PAUSE; 205 } 206 207 /* 208 * cleanup() - performs all ONE TIME cleanup for this test at 209 * completion or premature exit. 210 */ 211 void cleanup(void) 212 { 213 } 214