xref: /minix3/minix/tests/test68.c (revision 179bddcf5d405fd9e76b2f859b8ae1914df4a989)
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