2 #include <netinet/in.h>
3 #include <sys/socket.h>
6 #include <sys/syslimits.h>
17 #define CLOEXEC_PORT 3490
18 #define FORK_PORT 3491
22 void copy_subtests(void);
23 void test_open_file_cloexec(void);
24 void test_open_file_fork(void);
25 void test_open_socket_cloexec(void);
26 void test_open_socket_fork(void);
27 void start_socket_server(int port
);
28 int start_socket_client(int port
, int flag
);
33 char *subtests
[] = { "t67a", "t67b" };
34 char copy_cmd
[8 + PATH_MAX
+ 1];
37 no_tests
= sizeof(subtests
) / sizeof(char *);
39 for (i
= 0; i
< no_tests
; i
++) {
40 snprintf(copy_cmd
, 8 + PATH_MAX
, "cp ../%s .", subtests
[i
]);
46 test_open_file_cloexec()
51 /* Let's create a file with O_CLOEXEC turned on */
52 fd
= open("file", O_RDWR
|O_CREAT
|O_CLOEXEC
, 0660);
55 /* Now verify through fcntl the flag is indeed set */
56 flags
= fcntl(fd
, F_GETFD
);
58 if (!(flags
& FD_CLOEXEC
)) e(3);
60 /* Fork a child and let child exec a test program that verifies
61 * fd is not a valid file */
68 /* Verify again O_CLOEXEC is on */
69 flags
= fcntl(fd
, F_GETFD
);
71 if (!(flags
& FD_CLOEXEC
)) e(6);
73 snprintf(fd_buf
, sizeof(fd_buf
), "%d", fd
);
74 execl("./t67b", "t67b", fd_buf
, NULL
);
76 /* Should not reach this */
79 /* We're the parent */
82 if (waitpid(pid
, &result
, 0) == -1) e(7);
83 if (WEXITSTATUS(result
) != 0) e(8);
94 /* Let's create a file with O_CLOEXEC NOT turned on */
95 fd
= open("file", O_RDWR
|O_CREAT
, 0660);
98 /* Now verify through fcntl the flag is indeed not set */
99 flags
= fcntl(fd
, F_GETFD
);
101 if (flags
& FD_CLOEXEC
) e(3);
103 /* Fork a child and let child exec a test program that verifies
104 * fd is a valid file */
108 /* We're the child */
111 /* Verify again O_CLOEXEC is off */
112 flags
= fcntl(fd
, F_GETFD
);
114 if (flags
& FD_CLOEXEC
) e(6);
116 snprintf(fd_buf
, sizeof(fd_buf
), "%d", fd
);
117 execl("./t67a", "t67a", fd_buf
, NULL
);
119 /* Should not reach this */
122 /* We're the parent */
125 if (waitpid(pid
, &result
, 0) == -1) e(7);
126 if (WEXITSTATUS(result
) != 0) e(8);
132 start_socket_client(int port
, int flag
)
136 struct sockaddr_in server
;
138 if ((fd_sock
= socket(PF_INET
, SOCK_STREAM
|flag
, 0)) < 0) {
139 perror("Error obtaining socket\n");
143 if ((he
= gethostbyname("127.0.0.1")) == NULL
) {
144 perror("Error retrieving home\n");
148 /* Copy server host result */
149 memcpy(&server
.sin_addr
, he
->h_addr_list
[0], he
->h_length
);
150 server
.sin_family
= AF_INET
;
151 server
.sin_port
= htons(port
);
153 /* Normally, we'd zerofill sin_zero, but there is no such thing on
154 * Minix at the moment */
155 #if !defined(__minix)
156 memset(&server
.sin_zero
, '\0', sizeof(server
.sin_zero
));
159 if (connect(fd_sock
, (struct sockaddr
*) &server
, sizeof(server
)) < 0){
160 perror("Error connecting to server\n");
169 start_socket_server(int port
)
171 #if !defined(__minix)
175 struct sockaddr_in my_addr
;
176 struct sockaddr_in other_addr
;
177 socklen_t other_size
;
180 if ((fd_sock
= socket(PF_INET
, SOCK_STREAM
, 0)) < 0) {
181 perror("Error getting socket\n");
185 my_addr
.sin_family
= AF_INET
;
186 my_addr
.sin_port
= htons(port
);
187 my_addr
.sin_addr
.s_addr
= INADDR_ANY
;
188 /* Normally we'd zerofill sin_zero, but current Minix socket interface
189 * does not support that field */
190 #if !defined(__minix)
191 memset(&my_addr
.sin_zero
, '\0', sizeof(sin
.sin_zero
));
194 /* Reuse port number when invoking test often */
195 #if !defined(__minix)
196 if (setsockopt(fd_sock
, SOL_SOCKET
, SO_REUSEADDR
, &yes
,
198 perror("Error setting port reuse option\n");
204 if (bind(fd_sock
, (struct sockaddr
*) &my_addr
, sizeof(my_addr
)) < 0) {
205 perror("Error binding to port\n");
209 /* Set socket in listening mode */
210 if (listen(fd_sock
, 20) < 0) {
211 perror("Error listening for incoming connections");
215 /* Accept incoming connections */
216 fd_new
= accept(fd_sock
, (struct sockaddr
*) &other_addr
, &other_size
);
219 perror("Error accepting new connections\n");
223 (void)read(fd_new
, buf
, sizeof(buf
));
228 test_open_socket_cloexec()
230 /* This subtest will start a server and client using TCP. The client will
231 * open the socket with SOCK_CLOEXEC turned on, so that after a fork+exec, the
232 * socket should become invalid.
245 * | | (waitpid client_fork)
253 pid_t pid_server
, pid_client
;
257 if (pid_server
< 0) e(1);
258 if (pid_server
== 0) {
259 start_socket_server(CLOEXEC_PORT
);
260 return; /* Never reached */
264 if (pid_client
< 0) e(2);
265 if (pid_client
== 0) {
266 pid_t pid_client_fork
;
269 sockfd
= start_socket_client(CLOEXEC_PORT
, SOCK_CLOEXEC
);
270 if (sockfd
< 0) e(4);
272 pid_client_fork
= fork();
273 if (pid_client_fork
< 0) {
277 if (pid_client_fork
== 0) {
278 /* We're a fork of the client. After we exec, the
279 * socket should become invalid due to the SOCK_CLOEXEC
285 /* Verify O_CLOEXEC is on */
286 flags
= fcntl(sockfd
, F_GETFD
);
288 if (!(flags
& FD_CLOEXEC
)) e(6);
290 /* t67b will verify that it can't write to sockfd and
291 * that opening a new file will yield a file descriptor
292 * with the same number.
294 snprintf(sockfd_buf
, sizeof(sockfd_buf
), "%d", sockfd
);
295 execl("./t67b", "t67b", sockfd_buf
, NULL
);
297 /* Should not reach this */
300 if (waitpid(pid_client_fork
, &result
, 0) < 0) e(8);
301 exit(WEXITSTATUS(result
)); /* Pass on error to main */
303 exit(0); /* Never reached */
306 if (waitpid(pid_server
, &result
, 0) < 0) e(3);
307 if (waitpid(pid_client
, &result
, 0) < 0) e(4);
309 /* Let's inspect client result */
310 if (WEXITSTATUS(result
) != 0) e(5);
314 test_open_socket_fork(void)
316 /* This subtest will start a server and client using TCP. The client will
317 * open the socket with SOCK_CLOEXEC turned off, so that after a fork+exec, the
318 * socket should stay valid.
331 * | | (waitpid client_fork)
339 pid_t pid_server
, pid_client
;
343 if (pid_server
< 0) e(1);
344 if (pid_server
== 0) {
345 start_socket_server(FORK_PORT
);
346 return; /* Never reached */
350 if (pid_client
< 0) e(2);
351 if (pid_client
== 0) {
352 pid_t pid_client_fork
;
355 sockfd
= start_socket_client(FORK_PORT
, 0);
356 if (sockfd
< 0) e(4);
358 pid_client_fork
= fork();
359 if (pid_client_fork
< 0) {
363 if (pid_client_fork
== 0) {
364 /* We're a fork of the client. After we exec, the
365 * socket should stay valid due to lack of SOCK_CLOEXEC
371 /* Verify O_CLOEXEC is off */
372 flags
= fcntl(sockfd
, F_GETFD
);
374 if (flags
& FD_CLOEXEC
) e(6);
376 /* t67a will verify that it can't write to sockfd and
377 * that opening a new file will yield a file descriptor
378 * with a higher number.
380 snprintf(sockfd_buf
, sizeof(sockfd_buf
), "%d", sockfd
);
381 execl("./t67a", "t67a", sockfd_buf
, NULL
);
383 /* Should not reach this */
386 if (waitpid(pid_client_fork
, &result
, 0) < 0) e(8);
387 exit(WEXITSTATUS(result
)); /* Pass on error to main */
389 exit(0); /* Never reached */
392 if (waitpid(pid_server
, &result
, 0) < 0) e(3);
393 if (waitpid(pid_client
, &result
, 0) < 0) e(4);
395 /* Let's inspect client result */
396 if (WEXITSTATUS(result
) != 0) e(5);
400 main(int argc
, char *argv
[])
404 test_open_file_fork();
405 test_open_file_cloexec();
406 test_open_socket_fork();
407 test_open_socket_cloexec();
409 return(-1); /* Unreachable */