blob: 4eedd7a1003958f63ee6bc664d11267ff3af0ffa [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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#include "usctest.h"
55
56#define PIPEWRTCNT 100 /* must be an even number */
57
58char *TCID = "pipe09";
59int TST_TOTAL = 1;
60extern int Tst_count;
61
62void setup(void);
63void cleanup(void);
64
robbiewa728d282003-09-08 21:36:41 +000065ssize_t safe_read(int fd, void *buf, size_t count)
66{
67 ssize_t n;
68
69 do {
70 n = read(fd, buf, count);
71 } while (n < 0 && errno == EINTR);
72
73 return n;
74}
75
plars74948ad2002-11-14 16:16:14 +000076int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000077{
78 int lc; /* loop counter */
79 char *msg; /* message returned from parse_opts */
80
plars74948ad2002-11-14 16:16:14 +000081 int i, red, wtstatus;
plars865695b2001-08-27 22:15:12 +000082 int pipefd[2]; /* fds for pipe read/write */
plars865695b2001-08-27 22:15:12 +000083 char rebuf[BUFSIZ];
84 int Acnt = 0, Bcnt = 0; /* count 'A' and 'B' */
85 int fork_1, fork_2; /* ret values in parent */
86
87 /* parse standard options */
88 if ((msg = parse_opts(ac, av, (option_t *)NULL, NULL)) != (char *)NULL){
89 tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
90 /*NOTREACHED*/
91 }
92
93 setup();
94
95 for (lc = 0; TEST_LOOPING(lc); lc++) {
96
97 /* reset Tst_count in case we are looping */
98 Tst_count = 0;
99
100 TEST(pipe(pipefd));
101
102 if (TEST_RETURN == -1) {
103 tst_resm(TFAIL, "pipe() call failed");
104 continue;
105 }
106
107 if (!STD_FUNCTIONAL_TEST) {
108 tst_resm(TWARN, "-f option should not be used");
109 tst_resm(TPASS, "call succeeded");
110 continue;
111 }
112
robbiewd34d5812005-07-11 22:28:09 +0000113 if ((fork_1 = FORK_OR_VFORK()) == -1) {
plars865695b2001-08-27 22:15:12 +0000114 tst_brkm(TBROK, cleanup, "fork() #1 failed");
115 /*NOTREACHED*/
116 }
117
118 if (fork_1 == 0) { /* 1st child */
119 if (close(pipefd[0]) != 0) {
120 tst_resm(TWARN, "pipefd[0] close failed, "
121 "errno = %d", errno);
122 exit(1);
123 }
124
125 for (i = 0; i < PIPEWRTCNT / 2; ++i) {
126 if (write(pipefd[1], "A", 1) != 1) {
127 tst_resm(TWARN, "write to pipe failed");
128 exit(1);
129 }
130 }
131 exit(0);
132 }
133
134 /* parent */
135
136 waitpid(fork_1, &wtstatus, 0);
137 if (WEXITSTATUS(wtstatus) != 0) {
138 tst_brkm(TBROK, cleanup, "problem detected in child, "
139 "wait status %d, errno = %d", wtstatus, errno);
140 }
141
robbiewd34d5812005-07-11 22:28:09 +0000142 if ((fork_2 = FORK_OR_VFORK()) == -1) {
plars865695b2001-08-27 22:15:12 +0000143 tst_brkm(TBROK, cleanup, "fork() #2 failed");
144 /*NOTREACHED*/
145 }
146
147 if (fork_2 == 0) { /* 2nd child */
148 if (close(pipefd[0]) != 0) {
149 tst_resm(TWARN, "pipefd[0] close "
150 "failed, errno = %d", errno);
151 exit(1);
152 }
153
154 for (i = 0; i < PIPEWRTCNT / 2; ++i) {
155 if (write(pipefd[1], "B", 1) != 1) {
156 tst_resm(TWARN, "write to pipe failed");
157 exit(1);
158 }
159 }
160 exit(0);
161 }
162
163 /* parent */
164
165 waitpid(fork_2, &wtstatus, 0);
166 if (WEXITSTATUS(wtstatus) != 0) {
167 tst_brkm(TBROK, cleanup, "problem detected in child, "
168 "wait status %d, errno = %d", wtstatus, errno);
169 }
170
171 if (close(pipefd[1]) != 0) {
172 tst_brkm(TBROK, cleanup, "pipefd[1] close failed, "
173 "errno = %d", errno);
174 /*NOTREACHED*/
175 }
176
robbiewa728d282003-09-08 21:36:41 +0000177 while ((red = safe_read(pipefd[0], rebuf, 100)) > 0) {
plars865695b2001-08-27 22:15:12 +0000178 for (i = 0; i < red; i++) {
179 if (rebuf[i] == 'A') {
180 Acnt++;
181 continue;
182 }
183 if (rebuf[i] == 'B') {
184 Bcnt++;
185 continue;
186 }
187 tst_resm(TFAIL, "got bogus '%c' character",
188 rebuf[i]);
189 break;
190 }
191 }
192
193 if (red == -1) {
194 tst_brkm(TBROK, cleanup, "Failure reading pipefd pipe, "
195 "errno = %d", errno);
196 }
197
198 if (Bcnt == Acnt && Bcnt == (PIPEWRTCNT / 2)) {
199 tst_resm(TPASS, "functionality appears to be correct");
200 } else {
201 tst_resm(TFAIL, "functionality is not correct - Acnt "
202 "= %d, Bcnt = %d", Acnt, Bcnt);
203 }
204
205 /* clean up things in case we are looping */
206 Acnt = Bcnt = 0;
207 }
208 cleanup();
209
210 /*NOTREACHED*/
subrata_modak43337a32009-02-26 11:43:51 +0000211 return 0;
plars865695b2001-08-27 22:15:12 +0000212}
213
214/*
215 * setup() - performs all ONE TIME setup for this test.
216 */
217void
218setup()
219{
220 /* capture signals */
221 tst_sig(FORK, DEF_HANDLER, cleanup);
222
223 /* Pause if that option was specified */
224 TEST_PAUSE;
225}
226
227/*
228 * cleanup() - performs all ONE TIME cleanup for this test at
229 * completion or premature exit.
230 */
231void
232cleanup()
233{
234 /*
235 * print timing stats if that option was specified.
236 * print errno log if that option was specified.
237 */
238 TEST_CLEANUP;
239
240 /* exit with return code appropriate for results */
241 tst_exit();
242}