]> git.saurik.com Git - apple/xnu.git/blame - tools/tests/xnu_quick_test/socket_tests.c
xnu-1699.22.73.tar.gz
[apple/xnu.git] / tools / tests / xnu_quick_test / socket_tests.c
CommitLineData
2d21ac55
A
1/*
2 * socket_tests.c
3 * xnu_quick_test
4 *
5 * Created by Jerry Cottingham on 4/12/05.
6 * Copyright 2005 Apple Computer Inc. All rights reserved.
7 *
8 */
9
10#include "tests.h"
11#include <poll.h>
b0d623f7 12#include <mach/mach.h>
2d21ac55
A
13
14extern char g_target_path[ PATH_MAX ];
15
16/* **************************************************************************************************************
17 * Test accept, bind, connect, listen, socket, recvmsg, sendmsg, recvfrom, sendto, getpeername, getsockname
18 * system calls.
19 * WARNING - I don't do networking - this should get a good look from a networking stud.
20 * **************************************************************************************************************
21 */
22int socket_tests( void * the_argp )
23{
24 int my_err, my_status, my_len;
25 pid_t my_pid, my_wait_pid;
26 int my_socket_fd = -1;
27 int my_accepted_socket = -1;
28 char * my_parent_pathp = NULL;
29 char * my_child_pathp = NULL;
30 socklen_t my_accept_len;
31 struct sockaddr *my_sockaddr;
32 ssize_t my_result;
33 off_t my_current_offset;
34 char my_parent_socket_name[sizeof(struct sockaddr) + 64];
35 char my_child_socket_name[sizeof(struct sockaddr) + 64];
36 char my_accept_buffer[sizeof(struct sockaddr) + 64];
b0d623f7 37 kern_return_t my_kr;
2d21ac55
A
38
39 /* generate 2 names for binding to the sockets (one socket in the parent and one in the child) */
b0d623f7
A
40 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_parent_pathp, 128, VM_FLAGS_ANYWHERE);
41 if(my_kr != KERN_SUCCESS){
42 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
43 goto test_failed_exit;
44 }
45
46 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_child_pathp, 128, VM_FLAGS_ANYWHERE);
47 if(my_kr != KERN_SUCCESS){
48 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
49 goto test_failed_exit;
2d21ac55
A
50 }
51
52 *my_parent_pathp = 0x00;
53 strcat( my_parent_pathp, "/tmp/" );
54
55 /* get a unique name for our testing */
56 my_err = create_random_name( my_parent_pathp, 0 );
57 if ( my_err != 0 ) {
58 goto test_failed_exit;
59 }
60 strcpy( my_child_pathp, my_parent_pathp );
61 strcat( my_parent_pathp, "p" ); /* append 'p' to mean "parent" */
62 strcat( my_child_pathp, "c" ); /* append 'c' to mean "child" */
63
64 memset( &my_parent_socket_name[0], 0, sizeof(my_parent_socket_name) );
65 memset( &my_child_socket_name[0], 0, sizeof(my_child_socket_name) );
66
67 /* use unique names we generated in /tmp/ */
68 my_sockaddr = (struct sockaddr *) &my_parent_socket_name[0];
69 my_len = sizeof(*my_sockaddr) - sizeof(my_sockaddr->sa_data) + strlen(my_parent_pathp);
70 my_sockaddr->sa_len = my_len;
71 my_sockaddr->sa_family = AF_UNIX;
72 strcpy( &my_sockaddr->sa_data[0], my_parent_pathp );
73
74 my_sockaddr = (struct sockaddr *) &my_child_socket_name[0];
75 my_len = sizeof(*my_sockaddr) - sizeof(my_sockaddr->sa_data) + strlen(my_child_pathp);
76 my_sockaddr->sa_len = my_len;
77 my_sockaddr->sa_family = AF_UNIX;
78 strcpy( &my_sockaddr->sa_data[0], my_child_pathp );
79
80 /* set up socket for parent side */
81 my_socket_fd = socket( AF_UNIX, SOCK_STREAM, 0 );
82 if ( my_socket_fd == -1 ) {
83 printf( "socket call in parent failed with error %d - \"%s\" \n", errno, strerror( errno) );
84 goto test_failed_exit;
85 }
86 my_sockaddr = (struct sockaddr *) &my_parent_socket_name[0];
87 my_err = bind( my_socket_fd, my_sockaddr, my_sockaddr->sa_len );
88 if ( my_err == -1 ) {
89 printf( "bind call in child failed with error %d - \"%s\" \n", errno, strerror( errno) );
90 goto test_failed_exit;
91 }
92
93 /* test getsockname */
94 my_sockaddr = (struct sockaddr *) &my_accept_buffer[0];
95 my_accept_len = sizeof(my_accept_buffer);
96 my_err = getsockname( my_socket_fd, my_sockaddr, &my_accept_len );
97 if ( my_err == -1 ) {
98 printf( "getsockname call in child failed with error %d - \"%s\" \n", errno, strerror( errno) );
99 goto test_failed_exit;
100 }
101 if ( my_sockaddr->sa_family != SOCK_STREAM ) {
102 printf( "getsockname test failed - did not get correct socket name data \n" );
103 goto test_failed_exit;
104 }
105
106 /* make sure we can't seek on a socket */
107 my_current_offset = lseek( my_socket_fd, 0, SEEK_CUR );
108 if ( my_current_offset != -1 ) {
109 printf( "lseek on socket should fail but did not \n" );
110 goto test_failed_exit;
111 }
112
113 /*
114 * spin off a child process that we communicate with via sockets.
115 */
116 my_pid = fork( );
117 if ( my_pid == -1 ) {
118 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
119 goto test_failed_exit;
120 }
121 if ( my_pid == 0 ) {
122 /*
123 * child process - open a socket and use it to talk to our parent.
124 */
125 int my_child_fd = -1;
126 struct msghdr my_msghdr;
b0d623f7 127 struct iovec my_iov[4];
2d21ac55
A
128 char my_buffer[128];
129
130 my_child_fd = socket( AF_UNIX, SOCK_STREAM, 0 );
131 if ( my_child_fd == -1 ) {
132 printf( "socket call in child failed with error %d - \"%s\" \n", errno, strerror( errno) );
133 exit( -1 );
134 }
135
136 my_sockaddr = (struct sockaddr *) &my_child_socket_name[0];
137 my_err = bind( my_child_fd, my_sockaddr, my_sockaddr->sa_len );
138 if ( my_err == -1 ) {
139 close( my_child_fd );
140 printf( "bind call in child failed with error %d - \"%s\" \n", errno, strerror( errno) );
141 exit( -1 );
142 }
143 sleep(2);
144
145 /* connect to socket in our parent */
146 my_sockaddr = (struct sockaddr *) &my_parent_socket_name[0];
147 my_err = connect( my_child_fd, my_sockaddr, my_sockaddr->sa_len );
148 if ( my_err == -1 ) {
149 close( my_child_fd );
150 printf( "connect call in child failed with error %d - \"%s\" \n", errno, strerror( errno) );
151 exit( -1 );
152 }
153
154 /* get some data from the child via socket and test socket peer data */
155 {
156 socklen_t my_buffer_len;
157 struct sockaddr * my_sockaddr;
158 char my_parent_buffer[256];
159
160 my_sockaddr = (struct sockaddr *) &my_parent_buffer[0];
161 my_buffer_len = sizeof(my_parent_buffer);
162 my_err = getpeername( my_child_fd, my_sockaddr, &my_buffer_len );
163 if ( my_err == -1 ) {
164 printf( "getpeername call in parent failed with error %d - \"%s\" \n", errno, strerror( errno) );
165 goto test_failed_exit;
166 }
167
168 /* test results - should be sa_family == SOCK_STREAM and name should match my_child_pathp */
169 if ( my_sockaddr->sa_family != SOCK_STREAM ) {
170 printf( "getpeername test failed - did not get correct peer data \n" );
171 goto test_failed_exit;
172 }
173 }
174
175 my_buffer[0] = 'j';
b0d623f7
A
176 my_iov[0].iov_base = &my_buffer[0];
177 my_iov[0].iov_len = 1;
2d21ac55
A
178
179 my_sockaddr = (struct sockaddr *) &my_parent_socket_name[0];
180 my_msghdr.msg_name = my_sockaddr;
181 my_msghdr.msg_namelen = my_sockaddr->sa_len;
b0d623f7 182 my_msghdr.msg_iov = &my_iov[0];
2d21ac55
A
183 my_msghdr.msg_iovlen = 1;
184 my_msghdr.msg_control = NULL;
185 my_msghdr.msg_controllen = 0;
186 my_msghdr.msg_flags = 0;
187
188 my_result = sendmsg( my_child_fd, &my_msghdr, 0 );
189 if ( my_result == -1 ) {
190 printf( "sendmsg failed with error %d - \"%s\" \n", errno, strerror( errno) );
191 close( my_child_fd );
192 exit( -1 );
193 }
194
195#if 1
196 /* get data from our parent */
197 my_result = recvfrom( my_child_fd, &my_buffer[0], 1,
198 MSG_WAITALL, NULL, NULL );
199 if ( my_result == -1 ) {
200 printf( "recvfrom failed with error %d - \"%s\" \n", errno, strerror( errno) );
201 close( my_child_fd );
202 exit( -1 );
203 }
204
205 /* verify that we got the correct message from our child */
206 if ( my_buffer[0] != 'e' ) {
207 printf( "test failed - did not get correct data from child \n" );
208 close( my_child_fd );
209 exit( -1 );
210 }
211#endif
212
b0d623f7
A
213#if 1
214 /* sendfile test. Open libsystem, set up some headers, and send it */
6d2010ae
A
215 struct sf_hdtr my_sf_hdtr;
216 int my_libsys_fd;
217 off_t my_libsys_len;
218
219 my_libsys_fd = open("/usr/lib/libSystem.dylib", O_RDONLY, 0644);
220 if (my_libsys_fd < 0) {
221 printf( "test failed - could not open /usr/lib/libSystem.dylib\n" );
222 close ( my_child_fd );
223 exit ( -1 );
224 }
b0d623f7 225
6d2010ae
A
226 my_libsys_len = 7+2; /* 2 bytes of header */
227 my_buffer[0] = 's';
228 my_iov[0].iov_base = &my_buffer[0];
229 my_iov[0].iov_len = 1;
230 my_buffer[1] = 'e';
231 my_iov[1].iov_base = &my_buffer[1];
232 my_iov[1].iov_len = 1;
233 my_buffer[2] = 'n';
234 my_iov[2].iov_base = &my_buffer[2];
235 my_iov[2].iov_len = 1;
236 my_buffer[3] = 'd';
237 my_iov[3].iov_base = &my_buffer[3];
238 my_iov[3].iov_len = 1;
239
240 my_sf_hdtr.headers = &my_iov[0];
241 my_sf_hdtr.hdr_cnt = 2;
242 my_sf_hdtr.trailers = &my_iov[2];
243 my_sf_hdtr.trl_cnt = 2;
b0d623f7 244
6d2010ae
A
245 my_result = sendfile(my_libsys_fd, my_child_fd, 3, &my_libsys_len, &my_sf_hdtr, 0);
246 if (my_result < 0 || my_libsys_len != 11) {
247 printf( "sendfile failed with error %d - \"%s\" \n", errno, strerror( errno) );
248 close( my_child_fd );
249 exit( -1 );
250 }
b0d623f7 251
6d2010ae
A
252 my_result = close ( my_libsys_fd );
253 if ( my_libsys_fd < 0 ) {
254 printf ( "close failed with error %d - \"%s\" \n", errno, strerror( errno) );
255 close ( my_child_fd );
256 exit ( -1 );
257 }
b0d623f7
A
258#endif
259
2d21ac55
A
260 /* tell parent we're done */
261 my_result = write( my_child_fd, "all done", 8 );
262 if ( my_result == -1 ) {
263 close( my_child_fd );
264 exit( -1 );
265 }
266
267 close( my_child_fd );
268 exit(0);
269 }
270
271 /*
272 * parent process - listen for connection requests
273 */
274 my_err = listen( my_socket_fd, 10 );
275 if ( my_err == -1 ) {
276 printf( "listen call in parent failed with error %d - \"%s\" \n", errno, strerror( errno) );
277 goto test_failed_exit;
278 }
279
280 /* accept connection from child */
281 my_sockaddr = (struct sockaddr *) &my_accept_buffer[0];
282 my_accepted_socket = accept( my_socket_fd, my_sockaddr, &my_accept_len );
283 if ( my_accepted_socket == -1 ) {
284 printf( "accept call in parent failed with error %d - \"%s\" \n", errno, strerror( errno) );
285 goto test_failed_exit;
286 }
287
288 /* get some data from the child via socket and test socket peer data */
289 {
290 //socklen_t my_buffer_len;
291 struct msghdr my_msghdr;
292 struct iovec my_iov;
293 char my_parent_buffer[128];
294
295 my_parent_buffer[0] = 'x';
296 my_iov.iov_base = &my_parent_buffer[0];
297 my_iov.iov_len = 1;
298
299 my_msghdr.msg_name = &my_accept_buffer[0];
300 my_msghdr.msg_namelen = my_accept_len;
301 my_msghdr.msg_iov = &my_iov;
302 my_msghdr.msg_iovlen = 1;
303 my_msghdr.msg_control = NULL;
304 my_msghdr.msg_controllen = 0;
305 my_msghdr.msg_flags = 0;
306
307 my_result = recvmsg( my_accepted_socket, &my_msghdr, MSG_WAITALL );
308 if ( my_result == -1 ) {
309 printf( "recvmsg failed with error %d - \"%s\" \n", errno, strerror( errno) );
310 goto test_failed_exit;
311 }
312
313 /* verify that we got the correct message from our child */
314 if ( my_parent_buffer[0] != 'j' ) {
315 printf( "test failed - did not get correct data from child \n" );
316 goto test_failed_exit;
317 }
318
319#if 1
320 /* now send some data to our child */
321 my_parent_buffer[0] = 'e';
322 my_sockaddr = (struct sockaddr *) &my_child_socket_name[0];
323 my_result = sendto( my_accepted_socket, &my_parent_buffer[0], 1, 0, my_sockaddr,
324 my_sockaddr->sa_len );
325 if ( my_result == -1 ) {
326 printf( "sendto failed with error %d - \"%s\" \n", errno, strerror( errno) );
327 goto test_failed_exit;
328 }
329#endif
330
b0d623f7 331#if 1
6d2010ae 332 size_t neededBytes = 11;
b0d623f7 333
6d2010ae
A
334 /* Check for sendfile output */
335 bzero( (void *)&my_parent_buffer[0], sizeof(my_parent_buffer) );
336 while (neededBytes > 0) {
337 my_result = read( my_accepted_socket, &my_parent_buffer[11-neededBytes], neededBytes );
338 if ( my_result == -1 ) {
339 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
b0d623f7 340 goto test_failed_exit;
6d2010ae
A
341 } else if (my_result == 0) {
342 break;
b0d623f7 343 }
6d2010ae
A
344 neededBytes -= my_result;
345 }
346
347 if ( neededBytes > 0 ) {
348 printf( "read call returned %ld bytes instead of 11\n", 11 - neededBytes );
349 goto test_failed_exit;
350 }
b0d623f7 351
6d2010ae
A
352 if ( ! (my_parent_buffer[0] == 's' && my_parent_buffer[1] == 'e' && my_parent_buffer[9] == 'n' && my_parent_buffer[10] == 'd') ) {
353 printf( "read wrong sendfile message from child \n" );
354 goto test_failed_exit;
b0d623f7
A
355 }
356
357#endif
358
359 /* see if child is done. bzero so that string is NUL terminated */
2d21ac55
A
360 bzero( (void *)&my_parent_buffer[0], sizeof(my_parent_buffer) );
361 my_result = read( my_accepted_socket, &my_parent_buffer[0], sizeof(my_parent_buffer) );
362 if ( my_result == -1 ) {
363 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
364 goto test_failed_exit;
365 }
366 if ( strcmp( "all done", &my_parent_buffer[0] ) != 0 ) {
367 printf( "read wrong message from child \n" );
368 goto test_failed_exit;
369 }
370 }
371
372 /* wait for child to exit */
373 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
374 if ( my_wait_pid == -1 ) {
375 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
376 goto test_failed_exit;
377 }
378
379 if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
380 goto test_failed_exit;
381 }
382
383 my_err = 0;
384 goto test_passed_exit;
385
386test_failed_exit:
387 my_err = -1;
388
389test_passed_exit:
390 if ( my_socket_fd != -1 )
391 close( my_socket_fd );
392 if ( my_accepted_socket != -1 )
393 close( my_accepted_socket );
394 if ( my_parent_pathp != NULL ) {
395 remove( my_parent_pathp );
b0d623f7 396 vm_deallocate(mach_task_self(), (vm_address_t)my_parent_pathp, 128);
2d21ac55
A
397 }
398 if ( my_child_pathp != NULL ) {
399 remove( my_child_pathp );
b0d623f7 400 vm_deallocate(mach_task_self(), (vm_address_t)my_child_pathp, 128);
2d21ac55
A
401 }
402 return( my_err );
403}
404
405/* **************************************************************************************************************
406 * Test fsync, getsockopt, poll, select, setsockopt, socketpair system calls.
407 * **************************************************************************************************************
408 */
409int socket2_tests( void * the_argp )
410{
411 int my_err, my_status;
412 int my_sockets[ 2 ] = {-1, -1};
413 pid_t my_pid, my_wait_pid;
414 ssize_t my_count;
415 socklen_t my_socklen;
416 struct timeval * my_tvp;
417 struct timeval my_orig_tv;
418 char my_buffer[ 32 ];
419
420 my_err = socketpair( AF_UNIX, SOCK_STREAM, 0, &my_sockets[0] );
421 if ( my_err == -1 ) {
422 printf( "socketpair failed with errno %d - %s \n", errno, strerror( errno ) );
423 goto test_failed_exit;
424 }
425
426 /* test getsockopt and setsockopt */
427 my_socklen = sizeof( my_buffer );
428 my_err = getsockopt( my_sockets[0], SOL_SOCKET, SO_TYPE, &my_buffer[0], &my_socklen);
429 if ( my_err == -1 ) {
430 printf( "getsockopt - SO_TYPE - failed with errno %d - %s \n", errno, strerror( errno ) );
431 goto test_failed_exit;
432 }
433 if ( SOCK_STREAM != *((int *)&my_buffer[0]) ) {
434 printf( "getsockopt returned incorrect socket type \n" );
435 goto test_failed_exit;
436 }
437
438 /* get and set receive timeout */
439 my_socklen = sizeof( my_buffer );
440 my_err = getsockopt( my_sockets[0], SOL_SOCKET, SO_RCVTIMEO, &my_buffer[0], &my_socklen);
441 if ( my_err == -1 ) {
442 printf( "getsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno, strerror( errno ) );
443 goto test_failed_exit;
444 }
445 my_tvp = (struct timeval *) &my_buffer[0];
446 my_orig_tv.tv_sec = my_tvp->tv_sec;
447 my_orig_tv.tv_usec = my_tvp->tv_usec;
448
449 my_tvp->tv_sec += 60;
450 my_err = setsockopt( my_sockets[0], SOL_SOCKET, SO_RCVTIMEO, &my_buffer[0], sizeof(struct timeval) );
451 if ( my_err == -1 ) {
452 printf( "setsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno, strerror( errno ) );
453 goto test_failed_exit;
454 }
455
456 /* verify we set it */
457 my_socklen = sizeof( my_buffer );
458 my_err = getsockopt( my_sockets[0], SOL_SOCKET, SO_RCVTIMEO, &my_buffer[0], &my_socklen);
459 if ( my_err == -1 ) {
460 printf( "getsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno, strerror( errno ) );
461 goto test_failed_exit;
462 }
463 my_tvp = (struct timeval *) &my_buffer[0];
464 if ( my_tvp->tv_sec != (my_orig_tv.tv_sec + 60) || my_tvp->tv_usec != my_orig_tv.tv_usec ) {
465 printf( "setsockopt - SO_RCVTIMEO - did not set correct timeval \n" );
466 goto test_failed_exit;
467 }
468
469 /* set back to original receive timeout */
470 my_err = setsockopt( my_sockets[0], SOL_SOCKET, SO_RCVTIMEO, &my_orig_tv, sizeof(struct timeval) );
471 if ( my_err == -1 ) {
472 printf( "setsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno, strerror( errno ) );
473 goto test_failed_exit;
474 }
475
476 /* test fsync - should fail when used with a socket fd */
477 errno = 0;
478 my_err = fsync( my_sockets[0] );
479 if ( my_err == -1 && errno != ENOTSUP ) {
480 printf( "fsync failed with errno %d - %s \n", errno, strerror( errno ) );
481 goto test_failed_exit;
482 }
483 else if ( my_err != -1 ) {
484 printf( "fsync should have failed with errno ENOTSUP \n" );
485 goto test_failed_exit;
486 }
487
488 /*
489 * spin off a child process that we will talk to via our socketpair.
490 */
491 my_pid = fork( );
492 if ( my_pid == -1 ) {
493 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
494 goto test_failed_exit;
495 }
496 if ( my_pid == 0 ) {
497 /*
498 * child process - tell parent we are ready to go.
499 */
500 char my_buffer[ 32 ];
501 struct pollfd my_pollfd;
502
503 my_count = write( my_sockets[1], "r", 1 );
504 if ( my_count == -1 ) {
505 printf( "write call failed. got errno %d - %s. \n", errno, strerror( errno ) );
506 exit( -1 );
507 }
508
509 /* test select by using it to wait for message from parent */
510 for ( ;; ) {
511 fd_set my_read_set;
512 struct timeval my_timeout;
513
514 FD_ZERO( &my_read_set );
515 FD_SET( my_sockets[1], &my_read_set );
516 timerclear( &my_timeout );
517 my_timeout.tv_sec = 1;
518
519 /* check to see if we are done, if no message is ready after a second
520 * return and try again...
521 */
522 my_err = select( (my_sockets[1] + 1), &my_read_set, NULL, NULL, &my_timeout );
523 if ( my_err == -1 ) {
524 printf( "select call failed with error %d - \"%s\" \n", errno, strerror( errno) );
525 exit( -1 );
526 }
527 else if ( my_err > 0 ) {
528 /* we're done */
529 break;
530 }
531 }
532
533 /* test poll too */
534 my_pollfd.fd = my_sockets[1];
535 my_pollfd.events = (POLLIN | POLLPRI);
536 my_pollfd.revents = 0;
537 my_err = poll( &my_pollfd, 1, 500 );
538 if ( my_err == -1 ) {
539 printf( "poll call failed with error %d - \"%s\" \n", errno, strerror( errno) );
540 exit( -1 );
541 }
542 /* should be ready for read */
543 if ( (my_pollfd.revents & POLLIN) == 0 ) {
544 printf( "poll should have returned ready for read \n" );
545 exit( -1 );
546 }
547
548 my_count = read( my_sockets[1], &my_buffer[0], sizeof(my_buffer) );
549 if ( my_count == -1 ) {
550 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
551 exit( -1 );
552 }
553 if ( my_buffer[0] != 'd' ) {
554 printf( "read call on socket failed to get \"all done\" message \n" );
555 exit( -1 );
556 }
557
558 exit(0);
559 }
560
561 /*
562 * parent process - wait for child to spin up
563 */
564 my_count = read( my_sockets[0], &my_buffer[0], sizeof(my_buffer) );
565 if ( my_count == -1 ) {
566 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
567 goto test_failed_exit;
568 }
569 if ( my_buffer[0] != 'r' ) {
570 printf( "read call on socket failed to get \"ready to go message\" \n" );
571 goto test_failed_exit;
572 }
573
574 /* tell child we're done */
575 write( my_sockets[0], "d", 1 );
576
577 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
578 if ( my_wait_pid == -1 ) {
579 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
580 goto test_failed_exit;
581 }
582
583 /* wait4 should return our child's pid when it exits */
584 if ( my_wait_pid != my_pid ) {
585 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid, my_pid );
586 goto test_failed_exit;
587 }
588
589 if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
590 printf( "wait4 returned wrong exit status - 0x%02X \n", my_status );
591 goto test_failed_exit;
592 }
593
594 my_err = 0;
595 goto test_passed_exit;
596
597test_failed_exit:
598 my_err = -1;
599
600test_passed_exit:
601 if ( my_sockets[0] != -1 )
602 close( my_sockets[0] );
603 if ( my_sockets[1] != -1 )
604 close( my_sockets[1] );
605 return( my_err );
606}
607