globus_result_t
globus_i_gsi_cred_error_join_chains_result(
    globus_result_t                     outter_error,
    globus_result_t                     inner_error)
{
    globus_result_t                     result;
    globus_object_t *                   result_error_obj = NULL;
    globus_object_t *                   outter_error_obj = NULL;
    globus_object_t *                   inner_error_obj = NULL;
    globus_object_t *                   temp_error_obj = NULL;
    static char *                       _function_name_ =
        "globus_i_gsi_cred_error_join_chains";
    GLOBUS_I_GSI_CRED_DEBUG_ENTER;

    outter_error_obj = globus_error_get(outter_error);
    inner_error_obj = globus_error_get(inner_error);
    if(outter_error_obj && inner_error_obj)
    {
        temp_error_obj = outter_error_obj;
        while(globus_error_get_cause(temp_error_obj))
        {
            temp_error_obj = globus_error_get_cause(temp_error_obj);
        }

        temp_error_obj = globus_error_initialize_base(temp_error_obj,
                                                      globus_error_get_source(temp_error_obj),
                                                      inner_error_obj);
        result_error_obj = outter_error_obj;
    }
    else if(inner_error_obj)
    {
        result_error_obj = inner_error_obj;
    }
    else
    {
        result_error_obj = 
            globus_error_construct_error(
                GLOBUS_GSI_CREDENTIAL_MODULE,
                NULL,
                GLOBUS_GSI_CRED_ERROR_CREATING_ERROR_OBJ,
                __FILE__,
                _function_name_,
                __LINE__,
                "Couldn't join inner and outer error chains");
    }

    result = globus_error_put(result_error_obj);

    GLOBUS_I_GSI_CRED_DEBUG_EXIT;
    return result;
}
/**
 * Check whether the error originated from a specific module and
 * match a specific major status.
 * @ingroup globus_gssapi_error_utility  
 *
 * This function checks whether the error or any of it's causative
 * errors originated from a specific module and contains a specific
 * major status. If the module descriptor is left unspecified this
 * function  will check for any error of the specified major_status
 * and vice versa. 
 *
 * @param error
 *        The error object for which to perform the check
 * @param module
 *        The module descriptor to check for
 * @param major_status
 *        The major status to check for
 * @return
 *        GLOBUS_TRUE - the error matched the module and major status
 *        GLOBUS_FALSE - the error failed to match the module and
 *        major status
 */
globus_bool_t
globus_error_gssapi_match(
    globus_object_t *                   error,
    globus_module_descriptor_t *        module,
    const OM_uint32                     major_status)
{
    globus_module_descriptor_t *        source_module;
    int                                 current_major_status;
    
    if(error == NULL)
    {
        return GLOBUS_FALSE;
    }

    if(globus_object_get_type(error) != GLOBUS_ERROR_TYPE_GSSAPI)
    {
        /* not our type, skip it */
        return globus_error_gssapi_match(
            globus_error_get_cause(error),
            module,
            major_status);
    }

    source_module = globus_error_get_source(error);
    current_major_status = globus_error_gssapi_get_major_status(error);
    
    if(source_module == module && current_major_status == major_status)
    {
        return GLOBUS_TRUE;
    }
    else
    {
        return globus_error_gssapi_match(
            globus_error_get_cause(error),
            module,
            major_status);
    }
}/* globus_error_gssapi_match */
int
globus_error_ftp_error_get_code(
    globus_object_t *                   error)
{
    int                                 code = 0;
    globus_l_error_ftp_data_t *         data;
    
    do
    {
        if(globus_object_get_type(error) == GLOBUS_ERROR_TYPE_FTP)
        {
            data = (globus_l_error_ftp_data_t *)
                globus_object_get_local_instance_data(error);
            code = data->code;
        }
    } while(code == 0 && (error = globus_error_get_cause(error)));
    
    return code;
}
/**
 * Retrieve the minor status from a gssapi error object.
 * @ingroup globus_gssapi_error_accessor  
 *
 * @param error
 *        The error from which to retrieve the minor status
 * @return
 *        The minor status stored in the object
 */
OM_uint32
globus_error_gssapi_get_minor_status(
    globus_object_t *                   error)
{
    globus_l_gssapi_error_data_t *      data;
    
    data = (globus_l_gssapi_error_data_t *)
        globus_object_get_local_instance_data(error);
    if(data)
    {
        if(data->is_globus_gsi)
        {
            return (OM_uint32) globus_error_put(
                globus_object_copy(globus_error_get_cause(error)));
        }
        else
        {
            return data->minor_status;
        }
    }
    
    return 0;
}