char 		*pData, *pStart;
char 		*pData, *pStart, *pEnd;
ProcessProtocolSetup (iceConn, length, swap)IceConn		iceConn;unsigned long	length;Bool		swap;{    iceProtocolSetupMsg	*message;    _IcePaProtocol 	*myProtocol;    int  	      	myVersionCount, hisVersionCount;    int	 	      	myVersionIndex, hisVersionIndex;    int  	      	hisMajorVersion, hisMinorVersion;    int	 	      	myAuthCount, hisAuthCount;    int  	      	myOpcode, hisOpcode;    int	 	      	found, i, j;    char	      	*myAuthName, **hisAuthNames;    char 	      	*protocolName;    char 		*pData, *pStart;    char 	      	*vendor = NULL;    char 	      	*release = NULL;    int  	      	accept_setup_now = 0;    int			myAuthIndex = 0;    int			hisAuthIndex = 0;    char		mustAuthenticate;    int			authUsableCount;    int			authUsableFlags[MAX_ICE_AUTH_NAMES];    int			authIndices[MAX_ICE_AUTH_NAMES];    CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolSetup,	length, SIZEOF (iceProtocolSetupMsg), IceFatalToProtocol);    if (iceConn->want_to_close)    {	/*	 * If we sent a WantToClose message, but just got a ProtocolSetup,	 * we must cancel our WantToClose.  It is the responsiblity of the	 * other client to send a WantToClose later on.	 */	iceConn->want_to_close = 0;    }    IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolSetupMsg),	iceProtocolSetupMsg, message, pStart);    if (!IceValidIO (iceConn))    {	IceDisposeCompleteMessage (iceConn, pStart);	return (0);    }    pData = pStart;    SKIP_STRING (pData, swap);				       /* proto name */    SKIP_STRING (pData, swap);				       /* vendor */    SKIP_STRING (pData, swap);				       /* release */    SKIP_LISTOF_STRING (pData, swap, (int) message->authCount);/* auth names */    pData += (message->versionCount * 4);		       /* versions */    CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolSetup,	length, pData - pStart + SIZEOF (iceProtocolSetupMsg),	pStart, IceFatalToProtocol);    mustAuthenticate = message->mustAuthenticate;    if (mustAuthenticate != 0 && mustAuthenticate != 1)    {	_IceErrorBadValue (iceConn, 0,	    ICE_ProtocolSetup, 4, 1, &mustAuthenticate);	IceDisposeCompleteMessage (iceConn, pStart);	return (0);    }    pData = pStart;    if (iceConn->process_msg_info &&	(int) message->protocolOpcode >= iceConn->his_min_opcode &&        (int) message->protocolOpcode <= iceConn->his_max_opcode &&	iceConn->process_msg_info[	message->protocolOpcode - iceConn->his_min_opcode].in_use)    {	_IceErrorMajorOpcodeDuplicate (iceConn, message->protocolOpcode);	IceDisposeCompleteMessage (iceConn, pStart);	return (0);    }    EXTRACT_STRING (pData, swap, protocolName);    if (iceConn->process_msg_info)    {	for (i = 0;	    i <= (iceConn->his_max_opcode - iceConn->his_min_opcode); i++)	{	    if (iceConn->process_msg_info[i].in_use && strcmp (protocolName,	        iceConn->process_msg_info[i].protocol->protocol_name) == 0)	    {		_IceErrorProtocolDuplicate (iceConn, protocolName);		free (protocolName);		IceDisposeCompleteMessage (iceConn, pStart);		return (0);	    }	}    }    for (i = 0; i < _IceLastMajorOpcode; i++)	if (strcmp (protocolName, _IceProtocols[i].protocol_name) == 0)	    break;    if (i < _IceLastMajorOpcode &&        (myProtocol = _IceProtocols[i].accept_client) != NULL)    {	hisOpcode = message->protocolOpcode;	myOpcode = i + 1;	free (protocolName);    }    else    {	_IceErrorUnknownProtocol (iceConn, protocolName);	free (protocolName);	IceDisposeCompleteMessage (iceConn, pStart);	return (0);    }    EXTRACT_STRING (pData, swap, vendor);    EXTRACT_STRING (pData, swap, release);    if ((hisAuthCount = message->authCount) > 0)    {	hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));	EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);    }    hisVersionCount = message->versionCount;    myVersionCount = myProtocol->version_count;    hisVersionIndex = myVersionIndex = found = 0;    for (i = 0; i < hisVersionCount && !found; i++)    {	EXTRACT_CARD16 (pData, swap, hisMajorVersion);	EXTRACT_CARD16 (pData, swap, hisMinorVersion);	for (j = 0; j < myVersionCount && !found; j++)	{	    if (myProtocol->version_recs[j].major_version == hisMajorVersion &&		myProtocol->version_recs[j].minor_version == hisMinorVersion)	    {		hisVersionIndex = i;		myVersionIndex = j;		found = 1;	    }	}    }    if (!found)    {	_IceErrorNoVersion (iceConn, ICE_ProtocolSetup);	free (vendor);	free (release);	if (hisAuthCount > 0)	{	    for (i = 0; i < hisAuthCount; i++)		free (hisAuthNames[i]);		    free ((char *) hisAuthNames);	}	IceDisposeCompleteMessage (iceConn, pStart);	return (0);    }    myAuthCount = myProtocol->auth_count;    _IceGetPaValidAuthIndices (	_IceProtocols[myOpcode - 1].protocol_name,	iceConn->connection_string, myAuthCount, myProtocol->auth_names,        &authUsableCount, authIndices);    for (i = 0; i < myAuthCount; i++)    {	authUsableFlags[i] = 0;	for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)	    authUsableFlags[i] = (authIndices[j] == i);    }    for (i = found = 0; i < myAuthCount && !found; i++)    {	if (authUsableFlags[i])	{	    myAuthName = myProtocol->auth_names[i];	    for (j = 0; j < hisAuthCount && !found; j++)		if (strcmp (myAuthName, hisAuthNames[j]) == 0)		{		    myAuthIndex = i;		    hisAuthIndex = j;		    found = 1;		}	}    }    if (!found)    {	/*	 * None of the authentication methods specified by the	 * other client is supported.  If the other client requires	 * authentication, we must reject the Protocol Setup now.	 * Otherwise, we can invoke the host-based authentication callback	 * to see if we can accept this Protocol Setup.	 */	if (mustAuthenticate || !myProtocol->host_based_auth_proc)	{	    _IceErrorNoAuthentication (iceConn, ICE_ProtocolSetup);	}	else	{	    char *hostname = _IceGetPeerName (iceConn);	    if ((*myProtocol->host_based_auth_proc) (hostname))	    {		accept_setup_now = 1;	    }	    else 	    {		_IceErrorAuthenticationRejected (iceConn,	            ICE_ProtocolSetup, "None of the authentication protocols specified are supported and host-based authentication failed");	    }	    if (hostname)		free (hostname);	}    }    else    {	IcePaAuthStatus	status;	int 		authDataLen;	IcePointer 	authData = NULL;	IcePointer 	authState;	char		*errorString = NULL;	IcePaAuthProc	authProc =		myProtocol->auth_procs[myAuthIndex];	authState = NULL;	status = (*authProc) (iceConn, &authState, swap, 0, NULL,	    &authDataLen, &authData, &errorString);	if (status == IcePaAuthContinue)	{	    _IceProtoSetupToMeInfo *setupInfo;	    AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);	 	    iceConn->protosetup_to_me = setupInfo =		(_IceProtoSetupToMeInfo *) malloc (		sizeof (_IceProtoSetupToMeInfo));	    setupInfo->his_opcode = hisOpcode;	    setupInfo->my_opcode = myOpcode;	    setupInfo->my_version_index = myVersionIndex;	    setupInfo->his_version_index = hisVersionIndex;	    setupInfo->his_vendor = vendor;	    setupInfo->his_release = release;	    vendor = release = NULL;   /* so we don't free it */	    setupInfo->my_auth_index = myAuthIndex;	    setupInfo->my_auth_state = authState;	    setupInfo->must_authenticate = mustAuthenticate;	}	else if (status == IcePaAuthAccepted)	{	    accept_setup_now = 1;	}	if (authData && authDataLen > 0)	    free ((char *) authData);	if (errorString)	    free (errorString);    }    if (accept_setup_now)    {	IcePaProcessMsgProc		processMsgProc;	IceProtocolSetupProc		protocolSetupProc;	IceProtocolActivateProc		protocolActivateProc;	_IceProcessMsgInfo		*process_msg_info;	IcePointer			clientData = NULL;	char 				*failureReason = NULL;	Status				status = 1;	protocolSetupProc = myProtocol->protocol_setup_proc;	protocolActivateProc = myProtocol->protocol_activate_proc;	if (protocolSetupProc)	{	    /*	     * Notify the client of the Protocol Setup.	     */	    status = (*protocolSetupProc) (iceConn,		myProtocol->version_recs[myVersionIndex].major_version,		myProtocol->version_recs[myVersionIndex].minor_version,	        vendor, release, &clientData, &failureReason);	    vendor = release = NULL;   /* so we don't free it */	}	if (status != 0)	{	    /*	     * Send the Protocol Reply	     */	    AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex,	        myProtocol->vendor, myProtocol->release);	    /*	     * Set info for this protocol.	     */	    processMsgProc = myProtocol->version_recs[	        myVersionIndex].process_msg_proc;	    process_msg_info = &iceConn->process_msg_info[hisOpcode -	        iceConn->his_min_opcode];	    process_msg_info->client_data = clientData;	    process_msg_info->accept_flag = 1;	    process_msg_info->process_msg_proc.accept_client = processMsgProc;	    /*	     * Increase the reference count for the number of active protocols.	     */	    iceConn->proto_ref_count++;	    /*	     * Notify the client that the protocol is active.  The reason	     * we have this 2nd callback invoked is because the client	     * may wish to immediately generate a message for this	     * protocol, but it must wait until we send the Protocol Reply.	     */	    if (protocolActivateProc)	    {		(*protocolActivateProc) (iceConn,		    process_msg_info->client_data);	    }	}	else	{	    /*	     * An error was encountered.	     */	    _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason);	    if (failureReason)		free (failureReason);	}    }    if (vendor)	free (vendor);    if (release)	free (release);    if (hisAuthCount > 0)    {	for (i = 0; i < hisAuthCount; i++)	    free (hisAuthNames[i]);	free ((char *) hisAuthNames);    }    IceDisposeCompleteMessage (iceConn, pStart);    return (0);}