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> 12#include <mach/mach.h> 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]; 37 kern_return_t my_kr; 38 39 /* generate 2 names for binding to the sockets (one socket in the parent and one in the child) */ 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; 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; 127 struct iovec my_iov[4]; 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'; 176 my_iov[0].iov_base = &my_buffer[0]; 177 my_iov[0].iov_len = 1; 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; 182 my_msghdr.msg_iov = &my_iov[0]; 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 213#if !TARGET_OS_EMBEDDED 214 /* sendfile test. Open libsystem, set up some headers, and send it */ 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 } 225 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; 244 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 } 251 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 } 258#endif 259 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 331#if !TARGET_OS_EMBEDDED 332 size_t neededBytes = 11; 333 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) ); 340 goto test_failed_exit; 341 } else if (my_result == 0) { 342 break; 343 } 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 } 351 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; 355 } 356 357#endif 358 359 /* see if child is done. bzero so that string is NUL terminated */ 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 ); 396 vm_deallocate(mach_task_self(), (vm_address_t)my_parent_pathp, 128); 397 } 398 if ( my_child_pathp != NULL ) { 399 remove( my_child_pathp ); 400 vm_deallocate(mach_task_self(), (vm_address_t)my_child_pathp, 128); 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 608