SSL_set_info_callback(ssl,(void (*)())ptr);
{ union void_fn_to_char_u tmp_cb;  tmp_cb.char_p = ptr; SSL_set_info_callback(ssl,tmp_cb.fn_p); }
static long ssl_ctrl(BIO *b, int cmd, long num, char *ptr)	{	SSL **sslp,*ssl;	BIO_SSL *bs;	BIO *dbio,*bio;	long ret=1;	bs=(BIO_SSL *)b->ptr;	ssl=bs->ssl;	if ((ssl == NULL)  && (cmd != BIO_C_SET_SSL))		return(0);	switch (cmd)		{	case BIO_CTRL_RESET:		SSL_shutdown(ssl);		if (ssl->handshake_func == ssl->method->ssl_connect)			SSL_set_connect_state(ssl);		else if (ssl->handshake_func == ssl->method->ssl_accept)			SSL_set_accept_state(ssl);		SSL_clear(ssl);		if (b->next_bio != NULL)			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);		else if (ssl->rbio != NULL)			ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);		else			ret=1;		break;	case BIO_CTRL_INFO:		ret=0;		break;	case BIO_C_SSL_MODE:		if (num) /* client mode */			SSL_set_connect_state(ssl);		else			SSL_set_accept_state(ssl);		break;	case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT:		ret=bs->renegotiate_timeout;		if (num < 60) num=5;		bs->renegotiate_timeout=(unsigned long)num;		bs->last_time=(unsigned long)time(NULL);		break;	case BIO_C_SET_SSL_RENEGOTIATE_BYTES:		ret=bs->renegotiate_count;		if ((long)num >=512)			bs->renegotiate_count=(unsigned long)num;		break;	case BIO_C_GET_SSL_NUM_RENEGOTIATES:		ret=bs->num_renegotiates;		break;	case BIO_C_SET_SSL:		if (ssl != NULL)			ssl_free(b);		b->shutdown=(int)num;		ssl=(SSL *)ptr;		((BIO_SSL *)b->ptr)->ssl=ssl;		bio=SSL_get_rbio(ssl);		if (bio != NULL)			{			if (b->next_bio != NULL)				BIO_push(bio,b->next_bio);			b->next_bio=bio;			CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO);			}		b->init=1;		break;	case BIO_C_GET_SSL:		if (ptr != NULL)			{			sslp=(SSL **)ptr;			*sslp=ssl;			}		else			ret=0;		break;	case BIO_CTRL_GET_CLOSE:		ret=b->shutdown;		break;	case BIO_CTRL_SET_CLOSE:		b->shutdown=(int)num;		break;	case BIO_CTRL_WPENDING:		ret=BIO_ctrl(ssl->wbio,cmd,num,ptr);		break;	case BIO_CTRL_PENDING:		ret=SSL_pending(ssl);		if (ret == 0)			ret=BIO_pending(ssl->rbio);		break;	case BIO_CTRL_FLUSH:		BIO_clear_retry_flags(b);		ret=BIO_ctrl(ssl->wbio,cmd,num,ptr);		BIO_copy_next_retry(b);		break;	case BIO_CTRL_PUSH:		if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio))			{			SSL_set_bio(ssl,b->next_bio,b->next_bio);			CRYPTO_add(&b->next_bio->references,1,CRYPTO_LOCK_BIO);			}		break;	case BIO_CTRL_POP:		/* ugly bit of a hack */		if (ssl->rbio != ssl->wbio) /* we are in trouble :-( */			{			BIO_free_all(ssl->wbio);			}		ssl->wbio=NULL;		ssl->rbio=NULL;		break;	case BIO_C_DO_STATE_MACHINE:		BIO_clear_retry_flags(b);		b->retry_reason=0;		ret=(int)SSL_do_handshake(ssl);		switch (SSL_get_error(ssl,(int)ret))			{		case SSL_ERROR_WANT_READ:			BIO_set_flags(b,				BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);			break;		case SSL_ERROR_WANT_WRITE:			BIO_set_flags(b,				BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY);			break;		case SSL_ERROR_WANT_CONNECT:			BIO_set_flags(b,				BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);			b->retry_reason=b->next_bio->retry_reason;			break;		default:			break;			}		break;	case BIO_CTRL_DUP:		dbio=(BIO *)ptr;		if (((BIO_SSL *)dbio->ptr)->ssl != NULL)			SSL_free(((BIO_SSL *)dbio->ptr)->ssl);		((BIO_SSL *)dbio->ptr)->ssl=SSL_dup(ssl);		((BIO_SSL *)dbio->ptr)->renegotiate_count=			((BIO_SSL *)b->ptr)->renegotiate_count;		((BIO_SSL *)dbio->ptr)->byte_count=			((BIO_SSL *)b->ptr)->byte_count;		((BIO_SSL *)dbio->ptr)->renegotiate_timeout=			((BIO_SSL *)b->ptr)->renegotiate_timeout;		((BIO_SSL *)dbio->ptr)->last_time=			((BIO_SSL *)b->ptr)->last_time;		ret=(((BIO_SSL *)dbio->ptr)->ssl != NULL);		break;	case BIO_C_GET_FD:		ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);		break;	case BIO_CTRL_SET_CALLBACK:		SSL_set_info_callback(ssl,(void (*)())ptr);		break;	case BIO_CTRL_GET_CALLBACK:		{		void (**fptr)();		fptr=(void (**)())ptr;		*fptr=SSL_get_info_callback(ssl);		}		break;	default:		ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);		break;		}	return(ret);	}