connect_nonb.c 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. #include "unp.h"
  2. int
  3. connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec)
  4. {
  5. int flags, n, error;
  6. socklen_t len;
  7. fd_set rset, wset;
  8. struct timeval tval;
  9. flags = Fcntl(sockfd, F_GETFL, 0);
  10. Fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
  11. error = 0;
  12. if ( (n = connect(sockfd, saptr, salen)) < 0)
  13. if (errno != EINPROGRESS)
  14. return(-1);
  15. /* Do whatever we want while the connect is taking place. */
  16. if (n == 0)
  17. goto done; /* connect completed immediately */
  18. FD_ZERO(&rset);
  19. FD_SET(sockfd, &rset);
  20. wset = rset;
  21. tval.tv_sec = nsec;
  22. tval.tv_usec = 0;
  23. if ( (n = Select(sockfd+1, &rset, &wset, NULL,
  24. nsec ? &tval : NULL)) == 0) {
  25. close(sockfd); /* timeout */
  26. errno = ETIMEDOUT;
  27. return(-1);
  28. }
  29. if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
  30. len = sizeof(error);
  31. if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
  32. return(-1); /* Solaris pending error */
  33. } else
  34. err_quit("select error: sockfd not set");
  35. done:
  36. Fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
  37. if (error) {
  38. close(sockfd); /* just in case */
  39. errno = error;
  40. return(-1);
  41. }
  42. return(0);
  43. }