+/* NOTE: this is identical to analogous code in os-local.c */
+int
+ldap_int_poll(
+ LDAP *ld,
+ ber_socket_t s,
+ struct timeval *tvp )
+{
+ int rc;
+
+
+ osip_debug(ld, "ldap_int_poll: fd: %d tm: %ld\n",
+ s, tvp ? tvp->tv_sec : -1L, 0);
+
+#ifdef HAVE_POLL
+ {
+ struct pollfd fd;
+ int timeout = INFTIM;
+
+ fd.fd = s;
+ fd.events = POLL_WRITE;
+
+ if ( tvp != NULL ) {
+ timeout = TV2MILLISEC( tvp );
+ }
+ do {
+ fd.revents = 0;
+ rc = poll( &fd, 1, timeout );
+
+ } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
+ LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
+
+ if ( rc == AC_SOCKET_ERROR ) {
+ return rc;
+ }
+
+ if ( timeout == 0 && rc == 0 ) {
+ return -2;
+ }
+
+ if ( fd.revents & POLL_WRITE ) {
+ if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
+ return -1;
+ }
+
+ if ( ldap_pvt_ndelay_off( ld, s ) == -1 ) {
+ return -1;
+ }
+ return 0;
+ }
+ }
+#else
+ {
+ fd_set wfds, *z = NULL;
+#ifdef HAVE_WINSOCK
+ fd_set efds;
+#endif
+ struct timeval tv = { 0 };
+
+#if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK )
+ if ( s >= FD_SETSIZE ) {
+ rc = AC_SOCKET_ERROR;
+ tcp_close( s );
+ ldap_pvt_set_errno( EMFILE );
+ return rc;
+ }
+#endif
+
+ if ( tvp != NULL ) {
+ tv = *tvp;
+ }
+
+ do {
+ FD_ZERO(&wfds);
+ FD_SET(s, &wfds );
+
+#ifdef HAVE_WINSOCK
+ FD_ZERO(&efds);
+ FD_SET(s, &efds );
+#endif
+
+ rc = select( ldap_int_tblsize, z, &wfds,
+#ifdef HAVE_WINSOCK
+ &efds,
+#else
+ z,
+#endif
+ tvp ? &tv : NULL );
+ } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
+ LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
+
+ if ( rc == AC_SOCKET_ERROR ) {
+ return rc;
+ }
+
+ if ( rc == 0 && tvp && tvp->tv_sec == 0 && tvp->tv_usec == 0 ) {
+ return -2;
+ }
+
+#ifdef HAVE_WINSOCK
+ /* This means the connection failed */
+ if ( FD_ISSET(s, &efds) ) {
+ int so_errno;
+ ber_socklen_t dummy = sizeof(so_errno);
+ if ( getsockopt( s, SOL_SOCKET, SO_ERROR,
+ (char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno )
+ {
+ /* impossible */
+ so_errno = WSAGetLastError();
+ }
+ ldap_pvt_set_errno( so_errno );
+ osip_debug(ld, "ldap_int_poll: error on socket %d: "
+ "errno: %d (%s)\n", s, errno, sock_errstr( errno ));
+ return -1;
+ }
+#endif
+ if ( FD_ISSET(s, &wfds) ) {
+#ifndef HAVE_WINSOCK
+ if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
+ return -1;
+ }
+#endif
+ if ( ldap_pvt_ndelay_off(ld, s) == -1 ) {
+ return -1;
+ }
+ return 0;
+ }
+ }
+#endif
+
+ osip_debug(ld, "ldap_int_poll: timed out\n",0,0,0);
+ ldap_pvt_set_errno( ETIMEDOUT );
+ return -1;
+}
+