1433d6423SLionel Sambuc #include <sys/types.h>
2433d6423SLionel Sambuc #include <sys/wait.h>
3433d6423SLionel Sambuc #include <sys/syslimits.h>
4433d6423SLionel Sambuc #include <errno.h>
5433d6423SLionel Sambuc #include <fcntl.h>
6433d6423SLionel Sambuc #include <signal.h>
7433d6423SLionel Sambuc #include <stdio.h>
8433d6423SLionel Sambuc #include <stdlib.h>
9433d6423SLionel Sambuc #include <unistd.h>
10433d6423SLionel Sambuc
11433d6423SLionel Sambuc int max_error = 5;
12433d6423SLionel Sambuc #include "common.h"
13433d6423SLionel Sambuc
14433d6423SLionel Sambuc
15433d6423SLionel Sambuc void copy_subtests(void);
16433d6423SLionel Sambuc void test_pipe_cloexec(void);
17433d6423SLionel Sambuc void test_pipe_flag_setting(void);
18433d6423SLionel Sambuc void test_pipe_nonblock(void);
19433d6423SLionel Sambuc void test_pipe_normal(void);
20433d6423SLionel Sambuc void test_pipe_nosigpipe(void);
21433d6423SLionel Sambuc void alarm_handler(int sig);
22433d6423SLionel Sambuc void pipe_handler(int sig);
23433d6423SLionel Sambuc
24433d6423SLionel Sambuc static int seen_pipe_signal = 0;
25433d6423SLionel Sambuc static int seen_alarm_signal = 0;
26433d6423SLionel Sambuc
27433d6423SLionel Sambuc void
alarm_handler(int sig)28433d6423SLionel Sambuc alarm_handler(int sig)
29433d6423SLionel Sambuc {
30433d6423SLionel Sambuc if (seen_pipe_signal == 0)
31433d6423SLionel Sambuc seen_pipe_signal = -1;
32433d6423SLionel Sambuc seen_alarm_signal = 1;
33433d6423SLionel Sambuc }
34433d6423SLionel Sambuc
35433d6423SLionel Sambuc void
pipe_handler(int sig)36433d6423SLionel Sambuc pipe_handler(int sig)
37433d6423SLionel Sambuc {
38433d6423SLionel Sambuc seen_pipe_signal = 1;
39433d6423SLionel Sambuc }
40433d6423SLionel Sambuc
41433d6423SLionel Sambuc void
copy_subtests()42433d6423SLionel Sambuc copy_subtests()
43433d6423SLionel Sambuc {
44433d6423SLionel Sambuc char *subtests[] = { "t68a", "t68b" };
45433d6423SLionel Sambuc char copy_cmd[8 + PATH_MAX + 1];
46433d6423SLionel Sambuc int i, no_tests;
47433d6423SLionel Sambuc
48433d6423SLionel Sambuc no_tests = sizeof(subtests) / sizeof(char *);
49433d6423SLionel Sambuc
50433d6423SLionel Sambuc for (i = 0; i < no_tests; i++) {
51433d6423SLionel Sambuc snprintf(copy_cmd, 8 + PATH_MAX, "cp ../%s .", subtests[i]);
52433d6423SLionel Sambuc system(copy_cmd);
53433d6423SLionel Sambuc }
54433d6423SLionel Sambuc }
55433d6423SLionel Sambuc
56433d6423SLionel Sambuc void
test_pipe_normal()57433d6423SLionel Sambuc test_pipe_normal()
58433d6423SLionel Sambuc {
59433d6423SLionel Sambuc /* Verify pipe2 creates pipes that behave like a normal pipe */
60433d6423SLionel Sambuc
61433d6423SLionel Sambuc int pipes[2];
62433d6423SLionel Sambuc char buf_in[1], buf_out[1];
63433d6423SLionel Sambuc pid_t pid;
64433d6423SLionel Sambuc
65433d6423SLionel Sambuc subtest = 2;
66433d6423SLionel Sambuc
67433d6423SLionel Sambuc if (pipe2(pipes, 0) != 0) e(1);
68433d6423SLionel Sambuc
69433d6423SLionel Sambuc buf_out[0] = 'T';
70433d6423SLionel Sambuc if (write(pipes[1], buf_out, sizeof(buf_out)) != sizeof(buf_out)) e(2);
71433d6423SLionel Sambuc if (read(pipes[0], buf_in, sizeof(buf_in)) != sizeof(buf_in)) e(3);
72433d6423SLionel Sambuc if (buf_out[0] != buf_in[0]) e(4);
73433d6423SLionel Sambuc
74433d6423SLionel Sambuc /* When we close the write end, reading should fail */
75433d6423SLionel Sambuc if (close(pipes[1]) != 0) e(5);
76433d6423SLionel Sambuc if (read(pipes[0], buf_in, sizeof(buf_in)) != 0) e(6);
77433d6423SLionel Sambuc
78433d6423SLionel Sambuc /* Let's retry that experiment the other way around. Install a signal
79433d6423SLionel Sambuc * handler to catch SIGPIPE. Install an alarm handler to make sure
80433d6423SLionel Sambuc * this test finishes in finite time. */
81433d6423SLionel Sambuc if (pipe2(pipes, 0) != 0) e(7);
82433d6423SLionel Sambuc signal(SIGPIPE, pipe_handler);
83433d6423SLionel Sambuc signal(SIGALRM, alarm_handler);
84433d6423SLionel Sambuc seen_pipe_signal = 0;
85433d6423SLionel Sambuc seen_alarm_signal = 0;
86433d6423SLionel Sambuc alarm(1);
87433d6423SLionel Sambuc if (close(pipes[0]) != 0) e(8);
88433d6423SLionel Sambuc if (write(pipes[1], buf_out, sizeof(buf_out)) != -1) e(9);
89433d6423SLionel Sambuc while (seen_pipe_signal == 0)
90433d6423SLionel Sambuc ;
91433d6423SLionel Sambuc if (seen_pipe_signal != 1) e(10);
92433d6423SLionel Sambuc if (close(pipes[1]) != 0) e(11);
93433d6423SLionel Sambuc
94433d6423SLionel Sambuc /* Collect alarm signal */
95433d6423SLionel Sambuc while (seen_alarm_signal == 0)
96433d6423SLionel Sambuc ;
97433d6423SLionel Sambuc
98433d6423SLionel Sambuc if (pipe2(pipes, 0) != 0) e(12);
99433d6423SLionel Sambuc
100433d6423SLionel Sambuc /* Now fork and verify we can write to the pipe */
101433d6423SLionel Sambuc pid = fork();
102433d6423SLionel Sambuc if (pid < 0) e(13);
103433d6423SLionel Sambuc if (pid == 0) {
104433d6423SLionel Sambuc /* We're the child */
105433d6423SLionel Sambuc char fd_buf[2];
106433d6423SLionel Sambuc
107433d6423SLionel Sambuc /* Verify we can still write a byte into the pipe */
108433d6423SLionel Sambuc if (write(pipes[1], buf_out, sizeof(buf_out)) != 1) e(14);
109433d6423SLionel Sambuc
110433d6423SLionel Sambuc snprintf(fd_buf, sizeof(fd_buf), "%d", pipes[1]);
111433d6423SLionel Sambuc execl("./t68a", "t68a", fd_buf, NULL);
112433d6423SLionel Sambuc
113433d6423SLionel Sambuc exit(1); /* Should not be reached */
114433d6423SLionel Sambuc } else {
115433d6423SLionel Sambuc /* We're the parent */
116433d6423SLionel Sambuc int result;
117433d6423SLionel Sambuc
118433d6423SLionel Sambuc if (waitpid(pid, &result, 0) == -1) e(15);
119433d6423SLionel Sambuc if (WEXITSTATUS(result) != 0) e(16);
120433d6423SLionel Sambuc }
121433d6423SLionel Sambuc
122433d6423SLionel Sambuc if (close(pipes[0]) != 0) e(17);
123433d6423SLionel Sambuc if (close(pipes[1]) != 0) e(18);
124433d6423SLionel Sambuc }
125433d6423SLionel Sambuc
126433d6423SLionel Sambuc void
test_pipe_cloexec()127433d6423SLionel Sambuc test_pipe_cloexec()
128433d6423SLionel Sambuc {
129433d6423SLionel Sambuc /* Open a pipe with O_CLOEXEC */
130433d6423SLionel Sambuc int flags;
131433d6423SLionel Sambuc int pipes[2];
132433d6423SLionel Sambuc pid_t pid;
133433d6423SLionel Sambuc char buf_in[1], buf_out[1];
134433d6423SLionel Sambuc
135433d6423SLionel Sambuc subtest = 3;
136433d6423SLionel Sambuc
137433d6423SLionel Sambuc if (pipe2(pipes, O_CLOEXEC) != 0) e(1);
138433d6423SLionel Sambuc
139433d6423SLionel Sambuc /* Verify O_CLOEXEC flag is set */
140433d6423SLionel Sambuc flags = fcntl(pipes[0], F_GETFD);
141433d6423SLionel Sambuc if (flags < 0) e(2);
142433d6423SLionel Sambuc if (!(flags & FD_CLOEXEC)) e(3);
143433d6423SLionel Sambuc
144433d6423SLionel Sambuc pid = fork();
145433d6423SLionel Sambuc if (pid < 0) e(4);
146433d6423SLionel Sambuc if (pid == 0) {
147433d6423SLionel Sambuc /* We're the child */
148433d6423SLionel Sambuc char fd_buf[2];
149433d6423SLionel Sambuc
150433d6423SLionel Sambuc /* Verify we can still write a byte into the pipe */
151433d6423SLionel Sambuc buf_in[0] = 0;
152433d6423SLionel Sambuc buf_out[0] = 'T';
153433d6423SLionel Sambuc if (write(pipes[1], buf_out, sizeof(buf_out)) != 1) e(5);
154433d6423SLionel Sambuc if (read(pipes[0], buf_in, sizeof(buf_in)) != 1) e(6);
155433d6423SLionel Sambuc if (buf_out[0] != buf_in[0]) e(7);
156433d6423SLionel Sambuc
157433d6423SLionel Sambuc /* Verify FD_CLOEXEC flag is still set */
158433d6423SLionel Sambuc flags = fcntl(pipes[0], F_GETFD);
159433d6423SLionel Sambuc if (flags < 0) e(8);
160433d6423SLionel Sambuc if (!(flags & FD_CLOEXEC)) e(9);
161433d6423SLionel Sambuc
162433d6423SLionel Sambuc snprintf(fd_buf, sizeof(fd_buf), "%d", pipes[0]);
163433d6423SLionel Sambuc execl("./t68b", "t68b", fd_buf, NULL);
164433d6423SLionel Sambuc
165433d6423SLionel Sambuc exit(1); /* Should not be reached */
166433d6423SLionel Sambuc } else {
167433d6423SLionel Sambuc /* We're the parent */
168433d6423SLionel Sambuc int result;
169433d6423SLionel Sambuc
170433d6423SLionel Sambuc if (waitpid(pid, &result, 0) == -1) e(10);
171433d6423SLionel Sambuc if (WEXITSTATUS(result) != 0) e(11);
172433d6423SLionel Sambuc }
173433d6423SLionel Sambuc
174433d6423SLionel Sambuc /* Eventhough our child's pipe should've been closed upon exec, our
175433d6423SLionel Sambuc * pipe should still be functioning.
176433d6423SLionel Sambuc */
177433d6423SLionel Sambuc buf_in[0] = 0;
178433d6423SLionel Sambuc buf_out[0] = 't';
179433d6423SLionel Sambuc if (write(pipes[1], buf_out, sizeof(buf_out)) != sizeof(buf_out)) e(12);
180433d6423SLionel Sambuc if (read(pipes[0], buf_in, sizeof(buf_in)) != sizeof(buf_in)) e(13);
181433d6423SLionel Sambuc if (buf_out[0] != buf_in[0]) e(14);
182433d6423SLionel Sambuc
183433d6423SLionel Sambuc if (close(pipes[0]) != 0) e(15);
184433d6423SLionel Sambuc if (close(pipes[1]) != 0) e(16);
185433d6423SLionel Sambuc }
186433d6423SLionel Sambuc
187433d6423SLionel Sambuc void
test_pipe_nonblock()188433d6423SLionel Sambuc test_pipe_nonblock()
189433d6423SLionel Sambuc {
190433d6423SLionel Sambuc /* Open a pipe with O_NONBLOCK */
191433d6423SLionel Sambuc char *buf_in, *buf_out;
192433d6423SLionel Sambuc int pipes[2];
193433d6423SLionel Sambuc size_t pipe_size;
194433d6423SLionel Sambuc
195433d6423SLionel Sambuc subtest = 4;
196433d6423SLionel Sambuc
197433d6423SLionel Sambuc if (pipe2(pipes, O_NONBLOCK) != 0) e(1);
198433d6423SLionel Sambuc if ((pipe_size = fpathconf(pipes[0], _PC_PIPE_BUF)) == -1) e(2);
199433d6423SLionel Sambuc buf_in = calloc(2, pipe_size); /* Allocate twice the buffer size */
200433d6423SLionel Sambuc if (buf_in == NULL) e(3);
201433d6423SLionel Sambuc buf_out = calloc(2, pipe_size); /* Idem dito for output buffer */
202433d6423SLionel Sambuc if (buf_out == NULL) e(4);
203433d6423SLionel Sambuc
204433d6423SLionel Sambuc /* According to POSIX, a pipe with O_NONBLOCK set shall never block.
205433d6423SLionel Sambuc * When we attempt to write PIPE_BUF or less bytes, and there is
206433d6423SLionel Sambuc * sufficient space available, write returns nbytes. Else write will
207433d6423SLionel Sambuc * return -1 and not transfer any data.
208433d6423SLionel Sambuc */
209433d6423SLionel Sambuc if (write(pipes[1], buf_out, 1) != 1) e(5); /* Write 1 byte */
210433d6423SLionel Sambuc if (write(pipes[1], buf_out, pipe_size) != -1) e(6); /* Can't fit */
211433d6423SLionel Sambuc if (errno != EAGAIN) e(7);
212433d6423SLionel Sambuc
213433d6423SLionel Sambuc /* When writing more than PIPE_BUF bytes and when at least 1 byte can
214433d6423SLionel Sambuc * be tranferred, return the number of bytes written. We've written 1
215433d6423SLionel Sambuc * byte, so there are PIPE_BUF - 1 bytes left. */
216433d6423SLionel Sambuc if (write(pipes[1], buf_out, pipe_size + 1) != pipe_size - 1) e(8);
217433d6423SLionel Sambuc
218433d6423SLionel Sambuc /* Read out all data and try again. This time we should be able to
219433d6423SLionel Sambuc * write PIPE_BUF bytes. */
220433d6423SLionel Sambuc if (read(pipes[0], buf_in, pipe_size) != pipe_size) e(9);
221433d6423SLionel Sambuc if (read(pipes[0], buf_in, 1) != -1) e(10); /* Empty, can't read */
222433d6423SLionel Sambuc if (errno != EAGAIN) e(11);
223433d6423SLionel Sambuc if (write(pipes[1], buf_out, pipe_size + 1) != pipe_size) e(12);
224433d6423SLionel Sambuc if (close(pipes[0]) != 0) e(13);
225433d6423SLionel Sambuc if (close(pipes[1]) != 0) e(14);
226433d6423SLionel Sambuc free(buf_in);
227433d6423SLionel Sambuc free(buf_out);
228433d6423SLionel Sambuc }
229433d6423SLionel Sambuc
230433d6423SLionel Sambuc void
test_pipe_nosigpipe(void)231433d6423SLionel Sambuc test_pipe_nosigpipe(void)
232433d6423SLionel Sambuc {
233433d6423SLionel Sambuc /* Let's retry the writing to pipe without readers experiment. This time we set
234433d6423SLionel Sambuc * the O_NOSIGPIPE flag to prevent getting a signal. */
235433d6423SLionel Sambuc int pipes[2];
236433d6423SLionel Sambuc char buf_out[1];
237433d6423SLionel Sambuc
238433d6423SLionel Sambuc subtest = 5;
239433d6423SLionel Sambuc
240433d6423SLionel Sambuc if (pipe2(pipes, O_NOSIGPIPE) != 0) e(7);
241433d6423SLionel Sambuc signal(SIGPIPE, pipe_handler);
242433d6423SLionel Sambuc signal(SIGALRM, alarm_handler);
243433d6423SLionel Sambuc seen_pipe_signal = 0;
244433d6423SLionel Sambuc seen_alarm_signal = 0;
245433d6423SLionel Sambuc alarm(1);
246433d6423SLionel Sambuc if (close(pipes[0]) != 0) e(8);
247433d6423SLionel Sambuc if (write(pipes[1], buf_out, sizeof(buf_out)) != -1) e(9);
248433d6423SLionel Sambuc
249433d6423SLionel Sambuc /* Collect alarm signal */
250433d6423SLionel Sambuc while (seen_alarm_signal == 0)
251433d6423SLionel Sambuc ;
252433d6423SLionel Sambuc if (errno != EPIPE) e(10);
253433d6423SLionel Sambuc if (seen_pipe_signal != -1) e(11); /* Alarm sig handler set it to -1 */
254433d6423SLionel Sambuc if (close(pipes[1]) != 0) e(12);
255433d6423SLionel Sambuc }
256433d6423SLionel Sambuc
257433d6423SLionel Sambuc void
test_pipe_flag_setting()258433d6423SLionel Sambuc test_pipe_flag_setting()
259433d6423SLionel Sambuc {
260433d6423SLionel Sambuc int pipes[2];
261433d6423SLionel Sambuc
262433d6423SLionel Sambuc subtest = 1;
263433d6423SLionel Sambuc
264433d6423SLionel Sambuc /* Create standard pipe with no flags and verify they're off */
265433d6423SLionel Sambuc if (pipe2(pipes, 0) != 0) e(1);
266433d6423SLionel Sambuc if (fcntl(pipes[0], F_GETFD) != 0) e(2);
267433d6423SLionel Sambuc if (fcntl(pipes[1], F_GETFD) != 0) e(3);
268433d6423SLionel Sambuc if (fcntl(pipes[0], F_GETFL) & O_NONBLOCK) e(4);
269433d6423SLionel Sambuc if (fcntl(pipes[1], F_GETFL) & O_NONBLOCK) e(5);
2701f945e80SDavid van Moolenbroek if (fcntl(pipes[0], F_GETNOSIGPIPE) != 0) e(6);
2711f945e80SDavid van Moolenbroek if (fcntl(pipes[1], F_GETNOSIGPIPE) != 0) e(7);
272433d6423SLionel Sambuc if (close(pipes[0]) != 0) e(8);
273433d6423SLionel Sambuc if (close(pipes[1]) != 0) e(9);
274433d6423SLionel Sambuc
275433d6423SLionel Sambuc /* Create pipe with all flags and verify they're on */
276433d6423SLionel Sambuc if (pipe2(pipes, O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE) != 0) e(10);
277433d6423SLionel Sambuc if (fcntl(pipes[0], F_GETFD) != FD_CLOEXEC) e(11);
278433d6423SLionel Sambuc if (fcntl(pipes[1], F_GETFD) != FD_CLOEXEC) e(12);
279433d6423SLionel Sambuc if (!(fcntl(pipes[0], F_GETFL) & O_NONBLOCK)) e(13);
280433d6423SLionel Sambuc if (!(fcntl(pipes[1], F_GETFL) & O_NONBLOCK)) e(14);
2811f945e80SDavid van Moolenbroek if (fcntl(pipes[0], F_GETNOSIGPIPE) == 0) e(15);
2821f945e80SDavid van Moolenbroek if (fcntl(pipes[1], F_GETNOSIGPIPE) == 0) e(16);
2831f945e80SDavid van Moolenbroek if (fcntl(pipes[0], F_SETNOSIGPIPE, 0) != 0) e(17);
2841f945e80SDavid van Moolenbroek if (fcntl(pipes[0], F_GETNOSIGPIPE) != 0) e(18);
2851f945e80SDavid van Moolenbroek if (fcntl(pipes[0], F_SETNOSIGPIPE, 1) != 0) e(19);
2861f945e80SDavid van Moolenbroek if (fcntl(pipes[0], F_GETNOSIGPIPE) == 0) e(20);
2871f945e80SDavid van Moolenbroek if (close(pipes[0]) != 0) e(21);
2881f945e80SDavid van Moolenbroek if (close(pipes[1]) != 0) e(22);
289433d6423SLionel Sambuc }
290433d6423SLionel Sambuc
291*179bddcfSDavid van Moolenbroek /*
292*179bddcfSDavid van Moolenbroek * Test the behavior of a large pipe write that achieves partial progress
293*179bddcfSDavid van Moolenbroek * before the reader end is closed. The write call is expected to return EPIPE
294*179bddcfSDavid van Moolenbroek * and generate a SIGPIPE signal, and otherwise leave the system in good order.
295*179bddcfSDavid van Moolenbroek */
296*179bddcfSDavid van Moolenbroek static void
test_pipe_partial_write(void)297*179bddcfSDavid van Moolenbroek test_pipe_partial_write(void)
298*179bddcfSDavid van Moolenbroek {
299*179bddcfSDavid van Moolenbroek char buf[PIPE_BUF + 2];
300*179bddcfSDavid van Moolenbroek int pfd[2], status;
301*179bddcfSDavid van Moolenbroek
302*179bddcfSDavid van Moolenbroek signal(SIGPIPE, pipe_handler);
303*179bddcfSDavid van Moolenbroek
304*179bddcfSDavid van Moolenbroek if (pipe(pfd) < 0) e(1);
305*179bddcfSDavid van Moolenbroek
306*179bddcfSDavid van Moolenbroek switch (fork()) {
307*179bddcfSDavid van Moolenbroek case 0:
308*179bddcfSDavid van Moolenbroek close(pfd[1]);
309*179bddcfSDavid van Moolenbroek
310*179bddcfSDavid van Moolenbroek sleep(1); /* let the parent block on the write(2) */
311*179bddcfSDavid van Moolenbroek
312*179bddcfSDavid van Moolenbroek /*
313*179bddcfSDavid van Moolenbroek * This one-byte read raises the question whether the write
314*179bddcfSDavid van Moolenbroek * should return partial progress or not, since consumption of
315*179bddcfSDavid van Moolenbroek * part of its data is now clearly visible. NetBSD chooses
316*179bddcfSDavid van Moolenbroek * *not* to return partial progress, and MINIX3 follows suit.
317*179bddcfSDavid van Moolenbroek */
318*179bddcfSDavid van Moolenbroek if (read(pfd[0], buf, 1) != 1) e(2);
319*179bddcfSDavid van Moolenbroek
320*179bddcfSDavid van Moolenbroek sleep(1); /* let VFS retry satisfying the write(2) */
321*179bddcfSDavid van Moolenbroek
322*179bddcfSDavid van Moolenbroek exit(errct); /* close the reader side of the pipe */
323*179bddcfSDavid van Moolenbroek
324*179bddcfSDavid van Moolenbroek case -1:
325*179bddcfSDavid van Moolenbroek e(3);
326*179bddcfSDavid van Moolenbroek
327*179bddcfSDavid van Moolenbroek default:
328*179bddcfSDavid van Moolenbroek break;
329*179bddcfSDavid van Moolenbroek }
330*179bddcfSDavid van Moolenbroek
331*179bddcfSDavid van Moolenbroek close(pfd[0]);
332*179bddcfSDavid van Moolenbroek
333*179bddcfSDavid van Moolenbroek seen_pipe_signal = 0;
334*179bddcfSDavid van Moolenbroek
335*179bddcfSDavid van Moolenbroek /*
336*179bddcfSDavid van Moolenbroek * The following large write should block until the child exits, as
337*179bddcfSDavid van Moolenbroek * that is when the read end closes, thus making eventual completion of
338*179bddcfSDavid van Moolenbroek * the write impossible.
339*179bddcfSDavid van Moolenbroek */
340*179bddcfSDavid van Moolenbroek if (write(pfd[1], buf, sizeof(buf)) != -1) e(4);
341*179bddcfSDavid van Moolenbroek if (errno != EPIPE) e(5);
342*179bddcfSDavid van Moolenbroek if (seen_pipe_signal != 1) e(6);
343*179bddcfSDavid van Moolenbroek
344*179bddcfSDavid van Moolenbroek seen_pipe_signal = 0;
345*179bddcfSDavid van Moolenbroek
346*179bddcfSDavid van Moolenbroek /* A subsequent write used to cause a system crash. */
347*179bddcfSDavid van Moolenbroek if (write(pfd[1], buf, 1) != -1) e(7);
348*179bddcfSDavid van Moolenbroek if (errno != EPIPE) e(8);
349*179bddcfSDavid van Moolenbroek if (seen_pipe_signal != 1) e(9);
350*179bddcfSDavid van Moolenbroek
351*179bddcfSDavid van Moolenbroek /* Clean up. */
352*179bddcfSDavid van Moolenbroek close(pfd[1]);
353*179bddcfSDavid van Moolenbroek
354*179bddcfSDavid van Moolenbroek if (wait(&status) <= 0) e(10);
355*179bddcfSDavid van Moolenbroek if (!WIFEXITED(status)) e(11);
356*179bddcfSDavid van Moolenbroek errct += WEXITSTATUS(status);
357*179bddcfSDavid van Moolenbroek }
358*179bddcfSDavid van Moolenbroek
359433d6423SLionel Sambuc int
main(int argc,char * argv[])360433d6423SLionel Sambuc main(int argc, char *argv[])
361433d6423SLionel Sambuc {
362433d6423SLionel Sambuc start(68);
363433d6423SLionel Sambuc copy_subtests();
364433d6423SLionel Sambuc test_pipe_flag_setting();
365433d6423SLionel Sambuc test_pipe_normal();
366433d6423SLionel Sambuc test_pipe_cloexec();
367433d6423SLionel Sambuc test_pipe_nonblock();
368433d6423SLionel Sambuc test_pipe_nosigpipe();
369*179bddcfSDavid van Moolenbroek test_pipe_partial_write();
370433d6423SLionel Sambuc quit();
371433d6423SLionel Sambuc return(-1); /* Unreachable */
372433d6423SLionel Sambuc }
373433d6423SLionel Sambuc
374