LDAPRequest	*lr;
LDAPRequest	*lr = NULL;
wait4msg( LDAP *ld, int msgid, int all, int unlock_permitted,	struct timeval *timeout, LDAPMessage **result ){	int		rc;	struct timeval	tv, *tvp;	long		start_time = 0, tmp_time;	LDAPConn	*lc, *nextlc;	LDAPRequest	*lr;#ifdef LDAP_DEBUG	if ( timeout == NULL ) {		LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg (infinite timeout)\n",		    0, 0, 0 );	} else {		LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg (timeout %ld sec, %ld usec)\n",		    timeout->tv_sec, timeout->tv_usec, 0 );	}#endif /* LDAP_DEBUG */	/* check the cache */	if ( ld->ld_cache_on && ld->ld_cache_result != NULL ) {		/* if ( unlock_permitted ) LDAP_MUTEX_UNLOCK( ld ); */		LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );		rc = (ld->ld_cache_result)( ld, msgid, all, timeout, result );		LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );		/* if ( unlock_permitted ) LDAP_MUTEX_LOCK( ld ); */		if ( rc != 0 ) {			return( rc );		}		if ( ld->ld_cache_strategy == LDAP_CACHE_LOCALDB ) {			LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL, NULL );			return( 0 );	/* timeout */		}	}	/*	 * if we are looking for a specific msgid, check to see if it is	 * associated with a dead connection and return an error if so.	 */	if ( msgid != LDAP_RES_ANY && msgid != LDAP_RES_UNSOLICITED ) {		LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK );		if (( lr = nsldapi_find_request_by_msgid( ld, msgid ))		    == NULL ) {			LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );			LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL,				nsldapi_strdup( "unknown message id" ));			return( -1 );	/* could not find request for msgid */		}		if ( lr->lr_conn != NULL &&		    lr->lr_conn->lconn_status == LDAP_CONNST_DEAD ) {			nsldapi_free_request( ld, lr, 1 );			LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );			LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL );			return( -1 );	/* connection dead */		}		LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );	}	if ( timeout == NULL ) {		tvp = NULL;	} else {		tv = *timeout;		tvp = &tv;		start_time = (long)time( NULL );	}	rc = -2;	while ( rc == -2 ) {#ifdef LDAP_DEBUG		if ( ldap_debug & LDAP_DEBUG_TRACE ) {			nsldapi_dump_connection( ld, ld->ld_conns, 1 );			nsldapi_dump_requests_and_responses( ld );		}#endif /* LDAP_DEBUG */		LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK );		LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK );		for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {			if ( lc->lconn_sb->sb_ber.ber_ptr <			    lc->lconn_sb->sb_ber.ber_end ) {				rc = read1msg( ld, msgid, all, lc->lconn_sb,				    lc, result );				break;			}		}		LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );		LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK );		if ( lc == NULL ) {			rc = nsldapi_iostatus_poll( ld, tvp );#if defined( LDAP_DEBUG ) && !defined( macintosh ) && !defined( DOS )			if ( rc == -1 ) {			    LDAPDebug( LDAP_DEBUG_TRACE,				    "nsldapi_iostatus_poll returned -1: errno %d\n",				    LDAP_GET_ERRNO( ld ), 0, 0 );			}#endif#if !defined( macintosh ) && !defined( DOS )			if ( rc == 0 || ( rc == -1 && (( ld->ld_options &			    LDAP_BITOPT_RESTART ) == 0 ||			    LDAP_GET_ERRNO( ld ) != EINTR ))) {#else			if ( rc == -1 || rc == 0 ) {#endif				LDAP_SET_LDERRNO( ld, (rc == -1 ?				    LDAP_SERVER_DOWN : LDAP_TIMEOUT), NULL,				    NULL );				if ( rc == -1 ) {					LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK );					nsldapi_connection_lost_nolock( ld,						NULL );					LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );				}				return( rc );			}			if ( rc == -1 ) {				rc = -2;	/* select interrupted: loop */			} else {				rc = -2;				LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK );				LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK );				for ( lc = ld->ld_conns; rc == -2 && lc != NULL;				    lc = nextlc ) {					nextlc = lc->lconn_next;					if ( lc->lconn_status ==					    LDAP_CONNST_CONNECTED &&					    nsldapi_iostatus_is_read_ready( ld,					    lc->lconn_sb )) {						rc = read1msg( ld, msgid, all,						    lc->lconn_sb, lc, result );					}					else if (ld->ld_options & LDAP_BITOPT_ASYNC) {                        if ( lr                              && lc->lconn_status == LDAP_CONNST_CONNECTING                              && nsldapi_iostatus_is_write_ready( ld,			      lc->lconn_sb ) ) {                            rc = nsldapi_ber_flush( ld, lc->lconn_sb, lr->lr_ber, 0, 1 );                            if ( rc == 0 ) {                                rc = LDAP_RES_BIND;                                lc->lconn_status = LDAP_CONNST_CONNECTED;                                                                lr->lr_ber->ber_end = lr->lr_ber->ber_ptr;                                lr->lr_ber->ber_ptr = lr->lr_ber->ber_buf;                                nsldapi_iostatus_interest_read( ld, lc->lconn_sb );                            }                            else if ( rc == -1 ) {                                LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL );                                nsldapi_free_request( ld, lr, 0 );                                nsldapi_free_connection( ld, lc, NULL, NULL,				    0, 0 );                            }                        }                        					}				}				LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );				LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK );			}		}		/*		 * It is possible that recursion occurred while chasing		 * referrals and as a result the message we are looking		 * for may have been placed on the response queue.  Look		 * for it there before continuing so we don't end up		 * waiting on the network for a message that we already		 * received!		 */		if ( rc == -2 &&		    check_response_queue( ld, msgid, all, 0, result ) != 0 ) {			LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL );			rc = (*result)->lm_msgtype;		}		/*		 * honor the timeout if specified		 */		if ( rc == -2 && tvp != NULL ) {			tmp_time = (long)time( NULL );			if (( tv.tv_sec -=  ( tmp_time - start_time )) <= 0 ) {				rc = 0;	/* timed out */				LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL,				    NULL );				break;			}			LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg:  %ld secs to go\n",				tv.tv_sec, 0, 0 );			start_time = tmp_time;		}	}	return( rc );}