globus_result_t
globus_xio_driver_safe_table_from_string(
    char *                              driver_string,
    globus_hashtable_t *                safe_table)
{
    globus_result_t                     result;
    globus_xio_driver_list_ent_t *      d_ent;
    globus_list_t *                     driver_list = NULL;

    /* take advantage of xio function to load drivers */

    result = globus_xio_driver_list_from_string(
        driver_string, &driver_list, NULL);
    if(result != GLOBUS_SUCCESS)
    {
        goto error;
    }

    while(!globus_list_empty(driver_list))
    {
        d_ent = (globus_xio_driver_list_ent_t *)
            globus_list_remove(&driver_list, driver_list);

        globus_hashtable_insert(safe_table, d_ent->driver_name, d_ent);
    }

    return GLOBUS_SUCCESS;

error:

    return result;
}
int
globus_extension_register_builtin(
    const char *                        extension_name,
    globus_module_descriptor_t *        module_descriptor)
{
    globus_l_extension_builtin_t *      builtin;
    GlobusFuncName(globus_extension_register_builtin);
    
    GlobusExtensionDebugEnterSymbol(extension_name);
    
    builtin = (globus_l_extension_builtin_t *)
        globus_malloc(sizeof(globus_l_extension_builtin_t));
    if(!builtin)
    {
        goto error_alloc;
    }
    
    builtin->owner = (globus_l_extension_module_t *)
        globus_thread_getspecific(globus_l_extension_owner_key);
    builtin->module = module_descriptor;
    builtin->extension_name = globus_libc_strdup(extension_name);
    if(!builtin->extension_name)
    {
        goto error_strdup;
    }
    
    globus_rmutex_lock(&globus_l_extension_mutex);
    {
        int                             rc;
        
        rc = globus_hashtable_insert(
            &globus_l_extension_builtins, builtin->extension_name, builtin);
        if(rc != 0)
        {
            goto error_insert;
        }
    }
    globus_rmutex_unlock(&globus_l_extension_mutex);
    
    GlobusExtensionDebugExit();
    return GLOBUS_SUCCESS;

error_insert:
    globus_rmutex_unlock(&globus_l_extension_mutex);
    globus_free(builtin->extension_name);
error_strdup:
    globus_free(builtin);
error_alloc:
    GlobusExtensionDebugExitWithError();
    return GLOBUS_FAILURE;
}
/**
 * Register protocol.
 * @ingroup globus_gass_transfer_protocol
 *
 * This function registers a protocol module handler with the GASS Transfer
 * library. If this succeeds, then users of the library may use the URLs
 * with the protocol scheme implemented by this module descriptor in
 * GASS Transfer operations.
 *
 * @param proto_desc
 *        The protocol module descriptor. See the "@ref
 *        globus_gass_transfer_protocol" section of the manual for information
 *        on this structure.
 *
 * @retval GLOBUS_SUCCESS
 *         The protocol module was successfully registered with GASS.
 * @retval GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER
 *         The @a proto_desc parameter was @a GLOBUS_NULL.
 * @retval GLOBUS_GASS_TRANSFER_ERROR_ALREADY_REGISTERED
 *         A protocol module has already been registered with GASS to
 *         handle this URL scheme.
 */
int
globus_gass_transfer_proto_register_protocol(
    globus_gass_transfer_proto_descriptor_t *	proto_desc)
{
    int rc;


    if(proto_desc == GLOBUS_NULL)
    {
        return GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER;
    }

    rc = globus_hashtable_insert(&globus_i_gass_transfer_protocols,
			         proto_desc->url_scheme,
			         proto_desc);
    if(rc == -1)
    {
        return GLOBUS_GASS_TRANSFER_ERROR_ALREADY_REGISTERED;
    }
    else
    {
        return GLOBUS_SUCCESS;
    }
}
void
globus_module_setenv(
    const char *                        name,
    const char *                        value)
{
    int				rc;

    /*
     *  First, check to see if the environment mutex has been initialized
     */

    if(globus_l_environ_mutex_initialized == GLOBUS_FALSE)
    {
	if(globus_i_module_initialized == GLOBUS_TRUE)
	{
	    rc = globus_mutex_init(&globus_l_environ_hashtable_mutex,
                           (globus_mutexattr_t *) GLOBUS_NULL);
            globus_assert (rc == 0);
	    globus_l_environ_mutex_initialized = GLOBUS_TRUE;
	}
    }
   
    /*
     *  then, check to see if the environment hash table has been initialized
     */
 

    if((globus_l_environ_initialized == GLOBUS_FALSE))
    {
	if(globus_i_module_initialized==GLOBUS_TRUE)
	{
	    globus_mutex_lock(&globus_l_environ_hashtable_mutex);
	}

        globus_hashtable_init(&globus_l_environ_table,
                          GLOBUS_L_ENVIRON_TABLE_SIZE,
                          globus_hashtable_string_hash,
                          globus_hashtable_string_keyeq);

	globus_l_environ_initialized = GLOBUS_TRUE;

	if(globus_i_module_initialized == GLOBUS_TRUE)
	{
	    globus_mutex_unlock(&globus_l_environ_hashtable_mutex);
	}
    }

    /*
     *  Then actually put the name and value into the hash table
     */

    if(globus_i_module_initialized == GLOBUS_TRUE)
    {
	globus_mutex_lock(&globus_l_environ_hashtable_mutex);
    }

    globus_hashtable_remove(
	&globus_l_environ_table,
	(void *) name);
    globus_hashtable_insert(
         &globus_l_environ_table,
         (void *) name,
         (void *) value);

    if(globus_i_module_initialized == GLOBUS_TRUE)
    {
	globus_mutex_unlock(&globus_l_environ_hashtable_mutex);
    }

}
/**
 * Set the value of a header in a hashtable
 * @ingroup globus_i_xio_http_header
 *
 * Adds a new header to a header info structure, or updates the value of an
 * existing header. Copies of the name and value will be stored in a
 * #globus_xio_http_header_t in a hashtable in the header info structure.
 *
 * @param headers
 *     Pointer to the header info structure.
 * @param header_name
 *     Name of the header.
 * @param header_value
 *     Value of the header.
 *
 * @retval GLOBUS_SUCCESS
 *     Header successfully added to the hashtable.
 * @retval GLOBUS_XIO_ERROR_MEMORY
 *     Unable to add header due to memory constraints.
 */
globus_result_t
globus_i_xio_http_header_info_set_header(
    globus_i_xio_http_header_info_t *   headers,
    const char *                        header_name,
    const char *                        header_value)
{
    char *                              save_header;
    globus_result_t                     result = GLOBUS_SUCCESS;
    globus_xio_http_header_t *          header;
    int                                 rc;
    unsigned long                       length;
    GlobusXIOName(globus_l_xio_http_header_set);

    /* Special cases for entity-body handling headers */
    if (strcmp(header_name, "Content-Length") == 0)
    {
        rc = sscanf(header_value, "%lu", &length);

        if (rc < 1)
        {
            result = GlobusXIOHttpErrorInvalidHeader(header_name, header_value);

            goto error_exit;
        }
        headers->content_length = length;
        headers->flags |= GLOBUS_I_XIO_HTTP_HEADER_CONTENT_LENGTH_SET;
    }
    else if (strcmp(header_name, "Transfer-Encoding") == 0)
    {
        if (strcmp(header_value, "identity") == 0)
        {
            headers->transfer_encoding =
                GLOBUS_XIO_HTTP_TRANSFER_ENCODING_IDENTITY;
        }
        else if (strcmp(header_value, "chunked") == 0)
        {
            headers->transfer_encoding =
                GLOBUS_XIO_HTTP_TRANSFER_ENCODING_CHUNKED;
        }
        else
        {
            result = GlobusXIOHttpErrorInvalidHeader(header_name, header_value);

            goto error_exit;
        }
    }
    else if (strcmp(header_name, "Connection") == 0)
    {
        if (strcmp(header_value, "close") == 0)
        {
            headers->flags |= GLOBUS_I_XIO_HTTP_HEADER_CONNECTION_CLOSE;
        }
        else if (strcmp(header_value, "keep-alive") == 0)
        {
            headers->flags &= ~GLOBUS_I_XIO_HTTP_HEADER_CONNECTION_CLOSE;
        }
        else
        {
            result = GlobusXIOHttpErrorInvalidHeader(header_name, header_value);

            goto error_exit;
        }
    }
    else
    {
        /*
         * Either modify the header's value in the hashtable, if it's a
         * duplicate, or create a new entry in the hashtable
         */
        header = globus_hashtable_lookup(
                &headers->headers,
                (void *) header_name);

        if (header != NULL)
        {
            /* Replace current header's value */
            save_header = header->value;

            header->value = globus_libc_strdup(header_value);

            if (header->value == NULL)
            {
                header->value = save_header;

                result = GlobusXIOErrorMemory("header");

                goto error_exit;
            }
            globus_libc_free(save_header);
        }
        else
        {
            header = globus_libc_malloc(sizeof(globus_xio_http_header_t));

            if (header == NULL)
            {
                result = GlobusXIOErrorMemory("header");

                goto error_exit;
            }
            header->name = globus_libc_strdup(header_name);

            if (header->name == NULL)
            {
                result = GlobusXIOErrorMemory("header");
                goto free_header_exit;
            }

            header->value = globus_libc_strdup(header_value);

            if (header->value == NULL)
            {
                result = GlobusXIOErrorMemory("header");
                goto free_header_name_exit;
            }

            rc = globus_hashtable_insert(
                    &headers->headers,
                    header->name,
                    header);

            if (rc != GLOBUS_SUCCESS)
            {
                result = GlobusXIOErrorMemory("header");

                goto free_header_value_exit;
            }
        }
    }
    return result;

free_header_value_exit:
    globus_libc_free(header->value);
free_header_name_exit:
    globus_libc_free(header->name);
free_header_exit:
    globus_libc_free(header);
error_exit:
    return result;
}
/**
 * Call a callout of specified abstract type
 * @ingroup globus_callout_call
 *
 * This function looks up the callouts corresponding to the given type and
 * invokes them with the passed arguments. If a invoked callout returns an
 * error it will be chained to a error of the type
 * GLOBUS_CALLOUT_ERROR_CALLOUT_ERROR and no more callouts will be called.
 *
 * @param handle
 *        A configured callout handle
 * @param type
 *        The abstract type of the callout that is to be invoked
 * @return
 *        GLOBUS_SUCCESS
 *        A Globus error object on failure:
 *            GLOBUS_CALLOUT_ERROR_TYPE_NOT_REGISTERED
 *            GLOBUS_CALLOUT_ERROR_CALLOUT_ERROR
 *            GLOBUS_CALLOUT_ERROR_WITH_DL
 *            GLOBUS_CALLOUT_ERROR_WITH_HASHTABLE
 *            GLOBUS_CALLOUT_ERROR_OUT_OF_MEMORY
 */
globus_result_t
globus_callout_call_type(
    globus_callout_handle_t             handle,
    char *                              type,
    ...)
{
    globus_i_callout_data_t *           current_datum;
#ifdef BUILD_STATIC_ONLY
    void *                              function;
#else
    lt_ptr                              function;
    lt_dlhandle *                       dlhandle;
#endif
    globus_result_t                     result = GLOBUS_SUCCESS;
    va_list                             ap;
    int                                 rc;
    char *                              dlerror;
    char *                              flavor_start;
    char *                              file;
    char                                library[1024];
    char **                             save_env;
    int                                 i;
    globus_i_callout_data_t *           tmp_datum;
    int                                 mandatory_callouts_remaining = 0;
    static char *                       _function_name_ =
        "globus_callout_handle_call_type";
    GLOBUS_I_CALLOUT_DEBUG_ENTER;

    current_datum = globus_hashtable_lookup(&handle->symbol_htable,
                                            type);
    if(current_datum == NULL)
    {
        GLOBUS_CALLOUT_ERROR_RESULT(
            result,
            GLOBUS_CALLOUT_ERROR_TYPE_NOT_REGISTERED,
            ("unknown type: %s\n", type));
        goto exit;
    }
    
    tmp_datum = current_datum;
    while(tmp_datum)
    {
        if(tmp_datum->mandatory)
        {
            mandatory_callouts_remaining++;
        }
        tmp_datum = tmp_datum->next;
    }
    
    do
    {
#ifdef BUILD_STATIC_ONLY
        GLOBUS_CALLOUT_ERROR_RESULT(
            result,
            GLOBUS_CALLOUT_ERROR_WITH_DL,
            ("couldn't dlopen %s: %s\n",
             current_datum->file,
             "(null)"));
        goto exit;
#else
        dlhandle = globus_hashtable_lookup(&handle->library_htable,
                                           current_datum->file);

        if(dlhandle == NULL)
        {
            dlhandle = malloc(sizeof(lt_dlhandle));
            
            if(dlhandle == NULL)
            {
                GLOBUS_CALLOUT_MALLOC_ERROR(result);
            }
            
            *dlhandle = NULL;
            rc = globus_hashtable_insert(&handle->library_htable,
                                         current_datum->file,
                                         dlhandle);
            if(rc < 0)
            {
                free(dlhandle);
                GLOBUS_CALLOUT_ERROR_RESULT(
                    result,
                    GLOBUS_CALLOUT_ERROR_WITH_HASHTABLE,
                    ("globus_hashtable_insert retuned %d", rc));
                goto exit;
            }            
        }
    
        if(*dlhandle == NULL)
        {
            /* first time a symbol is referenced in this library ->
             * need to open it
             */
            
            *dlhandle = lt_dlopenext(current_datum->file);
            if(*dlhandle == NULL)
            {
                /* older libtools dont search the extensions correctly */
                snprintf(library, 1024, "%s" MY_LIB_EXT, current_datum->file);
                library[1023] = 0;
                *dlhandle = lt_dlopenext(library);
            }
            
            if(*dlhandle == NULL)
            {
                /* try again with flavor string removed */
                flavor_start = strrchr(current_datum->file, '_');
                if (flavor_start) {
                    file = strdup(current_datum->file);
                    if(file == NULL)
                        {
                            GLOBUS_CALLOUT_MALLOC_ERROR(result);
                            goto exit;
                        }
                    file[flavor_start - current_datum->file] = '\0';
                    *dlhandle = lt_dlopenext(file);
                    if(*dlhandle == NULL)
                    {
                        /* older libtools dont search the extensions correctly */
                        snprintf(library, 1024, "%s" MY_LIB_EXT, file);
                        library[1023] = 0;
                        *dlhandle = lt_dlopenext(library);
                    }
                    free(file);
                }
            }
            if(*dlhandle == NULL)
            {
                GLOBUS_CALLOUT_ERROR_RESULT(
                    result,
                    GLOBUS_CALLOUT_ERROR_WITH_DL,
                    ("couldn't dlopen %s: %s\n",
                     library,
                     (dlerror = lt_dlerror()) ? dlerror : 
                        "unknown error, possibly file not found."));
                goto exit;
            }
        }

        function = lt_dlsym(*dlhandle, current_datum->symbol);

        if(function == NULL)
        {
            GLOBUS_CALLOUT_ERROR_RESULT(
                result,
                GLOBUS_CALLOUT_ERROR_WITH_DL,
                ("symbol %s could not be found in %s: %s\n",
                 current_datum->symbol,
                 current_datum->file,
                 (dlerror = lt_dlerror()) ? dlerror : "(null)"));
            goto exit;
        }

        if(current_datum->env_args)
        {            
            save_env = globus_calloc(
                current_datum->num_env_args*2+1, sizeof(char *));

            i = 0;
            while(current_datum->env_args[i] != NULL && 
                current_datum->env_args[i+1] != NULL)
            {
                save_env[i] = current_datum->env_args[i];
                save_env[i+1] = 
                    globus_libc_strdup(getenv(current_datum->env_args[i]));
                setenv(current_datum->env_args[i], current_datum->env_args[i+1], 1);
                i += 2;
            }
            save_env[i] = NULL;
        }

        va_start(ap,type);
    
        result = ((globus_callout_function_t) function)(ap);
        
        va_end(ap);

        if(current_datum->env_args)
        {
            i = 0;            
            while(save_env[i] != NULL)
            {
                if(save_env[i+1] == NULL)
                {
                    unsetenv(save_env[i]);
                }
                else
                {
                    setenv(save_env[i], save_env[i+1], 1);
                    globus_free(save_env[i+1]);
                }
                                
                i += 2;
            }
            globus_free(save_env);
        }

        if(result == GLOBUS_SUCCESS)
        {
            if(current_datum->mandatory)
            {
                mandatory_callouts_remaining--;
            }
            
            if(!mandatory_callouts_remaining)
            {
                goto exit;
            }
        }
        
        if(result != GLOBUS_SUCCESS)
        {
            if(current_datum->mandatory)
            {
                GLOBUS_CALLOUT_ERROR_CHAIN_RESULT(
                    result,
                    GLOBUS_CALLOUT_ERROR_CALLOUT_ERROR);
                goto exit;
            }
            else if(current_datum->next == NULL)
            {
                /* chain error with stored error */
                GLOBUS_CALLOUT_ERROR_CHAIN_RESULT(
                    result,
                    GLOBUS_CALLOUT_ERROR_CALLOUT_ERROR);
                goto exit;
            }
            else
            {
                /* store error */
                result = GLOBUS_SUCCESS;
            }
        }

        current_datum = current_datum->next;
#endif
    }
    while(current_datum);
    
 exit:
    GLOBUS_I_CALLOUT_DEBUG_EXIT;
    return result;
}/*globus_callout_call_type*/
/**
 * Register callout configuration
 * @ingroup globus_callout_config
 *
 * This function registers a callout type in the given handle.
 *
 * @param handle
 *        The handle that is to be configured
 * @param type
 *        The abstract type of the callout
 * @param library
 *        The location of the library containing the callout
 * @param symbol
 *        The symbol (ie function name) for the callout
 * @return
 *        GLOBUS_SUCCESS
 *        A Globus error object on failure:
 *            GLOBUS_CALLOUT_ERROR_WITH_HASHTABLE
 *            GLOBUS_CALLOUT_ERROR_OUT_OF_MEMORY
 */
globus_result_t
globus_callout_register(
    globus_callout_handle_t             handle,
    char *                              type,
    char *                              library,
    char *                              symbol)
{
    int                                 rc;
    globus_result_t                     result;
    globus_i_callout_data_t *           datum = NULL;
    globus_i_callout_data_t *           existing_datum;
    char *                              flavor_start;
    
    static char *                       _function_name_ =
        "globus_callout_register";

    GLOBUS_I_CALLOUT_DEBUG_ENTER;
    
    
    /* push values into hash */

    datum = malloc(sizeof(globus_i_callout_data_t));
    
    if(datum == NULL)
    {
        GLOBUS_CALLOUT_MALLOC_ERROR(result);
        goto error_exit;
    }
    
    memset(datum,'\0',sizeof(globus_i_callout_data_t));

    if((flavor_start = strrchr(library,'_')) &&
       (strstr(flavor_start, "32") || strstr(flavor_start, "64")))
    {
        datum->file = strdup(library);
        
        if(datum->file == NULL)
        {
            GLOBUS_CALLOUT_MALLOC_ERROR(result);
            goto error_exit;
        }
    }
    else
    { 
        datum->file = malloc(strlen(library) + 2 + strlen(flavor));
        if(datum->file == NULL)
        {
            GLOBUS_CALLOUT_MALLOC_ERROR(result);
            goto error_exit;
        }
        datum->file[0] = '\0';
        strcat(datum->file, library);
        strcat(datum->file, "_");            
        strcat(datum->file, flavor);
    }
    
    datum->symbol = strdup(symbol);
    
    if(datum->symbol == NULL)
    {
        GLOBUS_CALLOUT_MALLOC_ERROR(result);
        goto error_exit;
    }
    
    datum->type = strdup(type);
    
    if(datum->type == NULL)
    {
        GLOBUS_CALLOUT_MALLOC_ERROR(result);
        goto error_exit;
    }
    
    if((rc = globus_hashtable_insert(&handle->symbol_htable,
                                     datum->type,
                                     datum)) == -1)
    {
        existing_datum = globus_hashtable_lookup(&handle->symbol_htable,
                                                 datum->type);
        while(existing_datum->next)
        {
            existing_datum = existing_datum->next;
        }
        existing_datum->next = datum;
    }
    else if(rc < 0)
    {
        GLOBUS_CALLOUT_ERROR_RESULT(
            result,
            GLOBUS_CALLOUT_ERROR_WITH_HASHTABLE,
            ("globus_hashtable_insert retuned %d", rc));
        goto error_exit;
    }
    
    GLOBUS_I_CALLOUT_DEBUG_EXIT;

    return GLOBUS_SUCCESS;

 error_exit:

    GLOBUS_I_CALLOUT_DEBUG_EXIT;
    
    if(datum != NULL)
    {
        globus_l_callout_data_free(datum);
    }
 
    return result;
}/*globus_callout_register*/
/**
 * Read callout configuration from file.
 * @ingroup globus_callout_config
 *
 * This function read a configuration file with the following format:
 *    - Anything after a '#' is assumed to be a comment
 *    - Blanks lines are ignored
 *    - Lines specifying callouts have the format
 *      abstract type           library         symbol
 *      where "abstract type" denotes the type of callout,
 *      e.g. globus_gram_jobmanager_authz, "library" denotes the library the
 *      callout can be found in and "symbol" denotes the function name of the
 *      callout. The library argument can be specified in two forms, libfoo or
 *      libfoo_<flavor>. When using the former version the current flavor will
 *      automatically be added to the library name. 
 *
 * @param handle
 *        The handle that is to be configured
 * @param filename
 *        The file to read configuration from
 * @return
 *        GLOBUS_SUCCESS
 *        A Globus error object on failure:
 *            GLOBUS_CALLOUT_ERROR_OPENING_CONF_FILE
 *            GLOBUS_CALLOUT_ERROR_PARSING_CONF_FILE
 *            GLOBUS_CALLOUT_ERROR_WITH_HASHTABLE
 *            GLOBUS_CALLOUT_ERROR_OUT_OF_MEMORY
 */
globus_result_t
globus_callout_read_config(
    globus_callout_handle_t             handle,
    char *                              filename)
{
    FILE *                              conf_file;
    char                                buffer[GLOBUS_I_CALLOUT_LINEBUF];
    char                                type[128];
    char                                library[256];
    char                                symbol[128];
    char *                              env_argstr;
    char **                             env_args;
    int                                 numpairs = 0;
    char *                              flavor_start;
    char *                              pound;
    int                                 index;
    int                                 rc;
    globus_result_t                     result;
    globus_i_callout_data_t *           datum = NULL;
    globus_i_callout_data_t *           existing_datum;
    

    static char *                       _function_name_ =
        "globus_callout_read_config";

    GLOBUS_I_CALLOUT_DEBUG_ENTER;
    
    conf_file = fopen(filename, "r");

    if(conf_file == NULL)
    {
        GLOBUS_CALLOUT_ERRNO_ERROR_RESULT(
            result,
            GLOBUS_CALLOUT_ERROR_OPENING_CONF_FILE,
            ("filename %s", filename));
        goto error_exit;
    }
    
    while(fgets(buffer,GLOBUS_I_CALLOUT_LINEBUF,conf_file))
    {
        if(!strchr(buffer, '\n'))
        {
            GLOBUS_CALLOUT_ERROR_RESULT(
                result,
                GLOBUS_CALLOUT_ERROR_PARSING_CONF_FILE,
                ("malformed line, line too long or missing newline"));
            goto error_exit;
        }

        /* strip any comments */
        pound = strchr(buffer, '#');

        if(pound != NULL)
        { 
            *pound = '\0';
        }

        /* strip white space from start */
        
        index = 0;

        while(buffer[index] == '\t' || buffer[index] == ' ')
        {
            index++;
        }

        /* if blank line continue */
        
        if(buffer[index] == '\0' || buffer[index] == '\n')
        { 
            continue;
        }
        
        if(sscanf(&buffer[index],"%127s%255s%127s",type,library,symbol) < 3)
        {
            GLOBUS_CALLOUT_ERROR_RESULT(
                result,
                GLOBUS_CALLOUT_ERROR_PARSING_CONF_FILE,
                ("malformed line: %s", &buffer[index]));
            goto error_exit;
        }
        
        /* check for ENV vars to set */
        env_argstr = strstr(buffer, "ENV:");
        if(env_argstr && strchr(env_argstr, '='))
        {
            int                         i;
            char *                      ptr;
            char *                      start;
            
            numpairs = 0;
            ptr = strchr(env_argstr, '=');
            while(ptr)
            {
                numpairs++;
                ptr++;
                if(*ptr == '"')
                {
                    ptr = strchr(ptr + 1, '"');
                    if(!ptr)
                    {
                        GLOBUS_CALLOUT_ERROR_RESULT(
                            result,
                            GLOBUS_CALLOUT_ERROR_PARSING_CONF_FILE,
                            ("malformed line, unmatched quote: %s", buffer));
                        goto error_exit;
                    }
                }
                ptr = strchr(ptr + 1, '=');
            }
            
            if(numpairs > 0)
            {
                env_args = globus_calloc(numpairs*2+1, sizeof(char *));
                
                start = env_argstr + 4;
                
                i = 0;
                while(start)
                {                    
                    /* skip initial space */
                    while(isspace(*start))
                    {
                        start++;
                    }
                    
                    /* find var name */
                    ptr = strchr(start, '=');
                    *ptr = '\0';
                    
                    if(strcspn(start, " \"=") != strlen(start))
                    {
                        GLOBUS_CALLOUT_ERROR_RESULT(
                            result,
                            GLOBUS_CALLOUT_ERROR_PARSING_CONF_FILE,
                            ("malformed line, invalid character in ENV var: %s", start));
                        goto error_exit;
                    }

                    env_args[i] = globus_libc_strdup(start);
                    
                    /* find value in quotes or before a space or end of line */
                    start = ++ptr;
                    
                    if(*start == '"')
                    {
                        start++;
                        ptr = strchr(start, '"');
                        *ptr = '\0';
                    }
                    else
                    {
                        ptr = strchr(start, ' ');
                        if(!ptr)
                        {
                            ptr = strchr(start, '\n');
                        }
                        *ptr = '\0';                        
                    }
                    env_args[i+1] = globus_libc_strdup(start);

                    ptr++;
                    while(*ptr && isspace(*ptr))
                    {
                        ptr++;
                    }
                    if(*ptr && strchr(ptr, '='))
                    {
                        start = ptr;
                    }
                    else
                    {
                        start = NULL;
                    }
                    
                    i += 2; 
                }
                env_args[i] = NULL;
            }
        }
        else
        {
            env_args = NULL;
        }
        
        /* push values into hash */
        datum = malloc(sizeof(globus_i_callout_data_t));

        if(datum == NULL)
        {
            GLOBUS_CALLOUT_MALLOC_ERROR(result);
            goto error_exit;
        }

        memset(datum,'\0',sizeof(globus_i_callout_data_t));

        /* check if library is flavored already */

        if((flavor_start = strrchr(library,'_')) &&
           (strstr(flavor_start, "32") || strstr(flavor_start, "64")))
        {
            datum->file = strdup(library);
            
            if(datum->file == NULL)
            {
                GLOBUS_CALLOUT_MALLOC_ERROR(result);
                goto error_exit;
            }
        }
        else
        { 
            datum->file = malloc(strlen(library) + 2 + strlen(flavor));
            if(datum->file == NULL)
            {
                GLOBUS_CALLOUT_MALLOC_ERROR(result);
                goto error_exit;
            }
            datum->file[0] = '\0';
            strcat(datum->file, library);
            strcat(datum->file, "_");
            strcat(datum->file, flavor);
        }
        
        datum->symbol = strdup(symbol);

        if(datum->symbol == NULL)
        {
            GLOBUS_CALLOUT_MALLOC_ERROR(result);
            goto error_exit;
        }
        
        if(*type == '|')
        {
            datum->mandatory = GLOBUS_FALSE;
            datum->type = strdup(type + 1);
        }
        else
        {
            datum->mandatory = GLOBUS_TRUE;
            datum->type = strdup(type);
        }

        if(datum->type == NULL)
        {
            GLOBUS_CALLOUT_MALLOC_ERROR(result);
            goto error_exit;
        }

        datum->env_args = env_args;
        datum->num_env_args = numpairs;

        if((rc = globus_hashtable_insert(&handle->symbol_htable,
                                         datum->type,
                                         datum)) == -1)
        {
            existing_datum = globus_hashtable_lookup(&handle->symbol_htable,
                                                     datum->type);
            while(existing_datum->next)
            {
                existing_datum = existing_datum->next;
            }
            existing_datum->next = datum;
        }
        else if(rc < 0)
        {
            GLOBUS_CALLOUT_ERROR_RESULT(
                result,
                GLOBUS_CALLOUT_ERROR_WITH_HASHTABLE,
                ("globus_hashtable_insert retuned %d", rc));
            goto error_exit;
        }
    }

    fclose(conf_file);
    
    GLOBUS_I_CALLOUT_DEBUG_EXIT;

    return GLOBUS_SUCCESS;

 error_exit:

    if(datum != NULL)
    {
        globus_l_callout_data_free(datum);
    }

    if(conf_file != NULL)
    {
        fclose(conf_file);
    }

    return result;
}/*globus_callout_read_config*/
/*
 * globus_l_gass_cache_config_init()
 *
 * Inits the config structure by reading from a file.
 *  
 * Parameters:
 *  - directory   the GASS cache directory 
 *  - config      the config structure
 *  
 * Returns:
 *  - GLOBUS_SUCCESS upon success
 */
int
globus_l_gass_cache_config_init(
    char *                          file,
    globus_l_gass_cache_config_t *  config)
{
    globus_off_t                    length;
    struct stat                     st;
    int                             i, n, fd, rc, status;
    char                            *p, *q, *r;
    char                            *key, *value;

    memset(config, '\0', sizeof(globus_l_gass_cache_config_t));

    status = GLOBUS_SUCCESS;

    config->buf = GLOBUS_NULL;

    /* open the config file, figure out size, then read the file into
       a buffer */
    fd = open(file, O_RDONLY);

    if (fd < 0)
    {
        status = GLOBUS_L_ERROR_CONFIG_FILE_NOT_FOUND;
        goto cleanup;
    }

    rc = fstat(fd, &st);
    if (rc < 0)
    {
        status = GLOBUS_L_ERROR_CONFIG_FILE_READ;
        goto cleanup;
    }

    length = st.st_size;

    config->buf = malloc(length+1);
    if (config->buf == NULL)
    {
        status = GLOBUS_GASS_CACHE_ERROR_NO_MEMORY;
        goto cleanup;
    }

    for (i=0; i<length; i+=n)
    {
        n = read(fd, config->buf+i, length-i);

        if (n <= 0)
        {
            status = GLOBUS_L_ERROR_CONFIG_FILE_READ;
            goto free_config_buf;
        }
    }
    *(config->buf+length) = '\0';
    
    rc = globus_hashtable_init(&config->table, 16, 
			       globus_hashtable_string_hash,
			       globus_hashtable_string_keyeq);
    if (rc != GLOBUS_SUCCESS)
    {
        status = GLOBUS_GASS_CACHE_ERROR_NO_MEMORY;
        goto free_config_buf;
    }

    for (p=config->buf; (p-config->buf)<length; p=q+1)
    {
	if (!(q = strchr(p, '\n')))
	    q = config->buf+length;

        *q = 0;

	strtrimhead(&p);
	strtrimtail(p);
	if (*p=='#' || !strlen(p))     /* a comment or empty line */
	    continue;

	r = strchr(p, '=');
        if (r == NULL)
        {
            status = GLOBUS_L_ERROR_CONFIG_FILE_PARSE_ERROR;

            goto destroy_hashtable;
        }

	*r = 0;
	key = p;
	value = r+1;
	
	strtrimtail(key);
	strtrimhead(&value);

	globus_hashtable_insert(&config->table,
				(void *) key,
				(void *) value);
    }
    if (fd >= 0)
    {
        close(fd);
    }

    return status;

destroy_hashtable:
    globus_hashtable_destroy(&config->table);
free_config_buf:
    free(config->buf);
    config->buf = NULL;
cleanup:
    if (fd >= 0)
    {
        close(fd);
    }
    return status;
}
/******************************************************************************
Function: globus_gass_server_ez_init()

Description: 

Parameters: 

Returns: 
******************************************************************************/
int
globus_gass_server_ez_init(globus_gass_transfer_listener_t * listener,
			   globus_gass_transfer_listenerattr_t * attr,
			   char * scheme,
			   globus_gass_transfer_requestattr_t * reqattr,
			   unsigned long options,
			   globus_gass_server_ez_client_shutdown_t callback,
               int fd)
{
    int rc;
    globus_l_gass_server_ez_t *server;
    globus_bool_t free_scheme=GLOBUS_FALSE;
    
    if(scheme==GLOBUS_NULL)
    {
	scheme=globus_malloc(6);  /* https/0 is the default */
	if(scheme == GLOBUS_NULL)
        {
            rc = GLOBUS_GASS_TRANSFER_ERROR_MALLOC_FAILED;
            goto error_exit;
        }
        free_scheme=GLOBUS_TRUE;
	globus_libc_lock();
        sprintf(scheme, "https");
        globus_libc_unlock();
    }

    if(reqattr==GLOBUS_NULL)
    {
	reqattr=(globus_gass_transfer_requestattr_t *)globus_malloc(sizeof(globus_gass_transfer_requestattr_t));

        globus_gass_transfer_requestattr_init(reqattr,
    					      scheme);
        globus_gass_transfer_secure_requestattr_set_authorization(reqattr,
							   GLOBUS_GASS_TRANSFER_AUTHORIZE_SELF,
							   scheme);
    }
    rc=globus_gass_transfer_create_listener(listener,
					    attr,
					    scheme);


    if(rc!=GLOBUS_SUCCESS)
    {
	goto error_exit;
    }

    server=(globus_l_gass_server_ez_t *)globus_malloc(
					sizeof (globus_l_gass_server_ez_t));
    if(server==GLOBUS_NULL)
    {
        rc = GLOBUS_GASS_TRANSFER_ERROR_MALLOC_FAILED;
	goto error_exit;
    }

    server->options=options;
    server->listener=*listener;
    server->reqattr=reqattr;
    server->callback=callback;
    server->fd=fd;

    globus_hashtable_insert(&globus_l_gass_server_ez_listeners,
			    (void *)*listener,
			    server);

    rc=globus_gass_transfer_register_listen(*listener,
				globus_l_gass_server_ez_listen_callback,
					(void *)reqattr);
/* insert error handling here*/

    error_exit:

    if (free_scheme) globus_free(scheme);

    return rc;
} /* globus_gass_server_ez_init() */
/*
 * PURPOSE:
 *     Verify that
 *     globus_gram_protocol_unpack_job_request_reply_with_extensions()
 *     deals with messages containing extension attributes not defined in the
 *     GRAM2
 *     protocol.
 * TEST STEPS:
 *   - Construct a status update message with the
 *     globus_gram_protocol_pack_job_request_reply_with_extensions()
 *     function.
 *   - Call globus_gram_protocol_unpack_job_request_reply_with_extensions() and
 *     expect a GLOBUS_SUCCESS
 *   - Check that our new attribute is in the hash
 */
int
test_extra_attributes(void)
{
    globus_byte_t *                     message;
    globus_size_t                       message_size;
    globus_hashtable_t                  hashtable;
    globus_gram_protocol_extension_t *  entry;
    int                                 rc;
    char *                              expected[] =
    {
            "protocol-version",
            "status",
            "job-manager-url",
            "attribute"
    };
    int                                 i;
    int                                 status;
    char *                              job_contact;

    rc = globus_hashtable_init(
            &hashtable,
            89,
            globus_hashtable_string_hash,
            globus_hashtable_string_keyeq);
    test_assert(
            rc == GLOBUS_SUCCESS,
            ("Error initializing hashtable (out of memory?)\n"));
    entry = malloc(sizeof(globus_gram_protocol_extension_t));
    test_assert(entry != NULL,
            ("Error allocating hash entry (out of memory?)\n"));
    entry->attribute = "attribute";
    entry->value = "value";
    rc = globus_hashtable_insert(&hashtable, entry->attribute, entry);

    rc = globus_gram_protocol_pack_job_request_reply_with_extensions(
            GLOBUS_GRAM_PROTOCOL_JOB_STATE_ACTIVE,
            "https://example.org:123/12/34",
            &hashtable,
            &message,
            &message_size);
    test_assert(rc == GLOBUS_SUCCESS,
            ("Error packing status message: %d (%s)\n",
            rc, globus_gram_protocol_error_string(rc)));

    globus_hashtable_destroy(&hashtable);
    free(entry);
    hashtable = NULL;

    test_assert(
            rc == GLOBUS_SUCCESS,
            ("Error constructing test message: %d (%s)\n",
            rc,
            globus_gram_protocol_error_string(rc)));

    rc = globus_gram_protocol_unpack_job_request_reply_with_extensions(
            message,
            message_size,
            &status,
            &job_contact,
            &hashtable);
    test_assert(
            rc == GLOBUS_SUCCESS,
            ("Error parsing test message: %d (%s)\n",
            rc,
            globus_gram_protocol_error_string(rc)));

    /* check that expected attributes were parsed */
    for (i = 0; i < ARRAY_LEN(expected); i++)
    {
        entry = globus_hashtable_lookup(&hashtable, expected[i]);
        test_assert(
                entry != NULL,
                ("Missing expected attribute %s\n", expected[i]));
    }

    test_assert(ARRAY_LEN(expected) == globus_hashtable_size(&hashtable),
            ("Hash table contains %d entries, expected %d",
             globus_hashtable_size(&hashtable),
             ARRAY_LEN(expected)));

    globus_gram_protocol_hash_destroy(&hashtable);

    free(message);

    return 0;
}
int
globus_extension_registry_add(
    globus_extension_registry_t *       registry,
    void *                              symbol,
    globus_module_descriptor_t *        module,
    void *                              data)
{
    globus_l_extension_handle_t *       entry;
    GlobusFuncName(globus_extension_registry_add);
    
    GlobusExtensionDebugEnterSymbol(registry->user_hashing ? "" : symbol);
    
    if(!data || !symbol || !registry)
    {
        goto error_params;
    }
    
    entry = (globus_l_extension_handle_t *)
        globus_malloc(sizeof(globus_l_extension_handle_t));
    if(!entry)
    {
        goto error_malloc;
    }
    
    entry->owner = (globus_l_extension_module_t *)
        globus_thread_getspecific(globus_l_extension_owner_key);
    entry->module = module;
    entry->datum = data;
    entry->ref = 1;
    entry->symbol = symbol;
    entry->user_hashing = registry->user_hashing;
    
    globus_rmutex_lock(&globus_l_extension_mutex);
    {
        if(!registry->initialized)
        {
            if(globus_hashtable_init(
                &registry->table,
                20,
                globus_hashtable_string_hash,
                globus_hashtable_string_keyeq) != GLOBUS_SUCCESS)
            {
                goto error_init;
            }
            
            registry->initialized = GLOBUS_TRUE;
        }
        
        if(globus_hashtable_insert(
            &registry->table, entry->symbol, entry) != GLOBUS_SUCCESS)
        {
            goto error_insert;
        }
    }
    globus_rmutex_unlock(&globus_l_extension_mutex);
    
    GlobusExtensionDebugExit();
    return GLOBUS_SUCCESS;

error_insert:
error_init:
    globus_rmutex_unlock(&globus_l_extension_mutex);
    globus_free(entry);
error_malloc:
error_params:
    GlobusExtensionDebugExitWithError();
    return GLOBUS_FAILURE;
}
int
globus_extension_activate(
    const char *                        extension_name)
{
    globus_l_extension_module_t *       extension;
    globus_l_extension_module_t *       last_extension;
    globus_l_extension_builtin_t *      builtin;
    int                                 rc;
    globus_result_t                     result = GLOBUS_FAILURE;
    GlobusFuncName(globus_extension_activate);
    
    GlobusExtensionDebugEnterSymbol(extension_name);
    
    if(!extension_name)
    {
        goto error_param;
    }
    
    globus_rmutex_lock(&globus_l_extension_mutex);
    {
        extension = (globus_l_extension_module_t *)
            globus_hashtable_lookup(
                &globus_l_extension_loaded, (void *) extension_name);
        if(!extension)
        {
            extension = (globus_l_extension_module_t *)
                globus_malloc(sizeof(globus_l_extension_module_t));
            if(!extension)
            {
                goto error_alloc;
            }
            
            extension->module_ref = 1;
            extension->ref = 1;
            extension->name = globus_libc_strdup(extension_name);
            if(!extension->name)
            {
                goto error_strdup;
            }
            
            builtin = (globus_l_extension_builtin_t *)
                globus_hashtable_lookup(
                    &globus_l_extension_builtins, (void *) extension_name);
            if(builtin && (!builtin->owner || builtin->owner->module_ref > 0))
            {
#               if !defined(BUILD_STATIC_ONLY)
                {

                    extension->dlhandle = NULL;
                }
#               endif
                extension->module = builtin->module;
                extension->owner = builtin->owner;
                if(extension->owner)
                {
                    extension->owner->ref++;
                }
            }
            else
            {
                extension->owner = NULL;

#               if !defined(BUILD_STATIC_ONLY)
                {

                    result =   
                        globus_l_extension_dlopen(
                            extension->name,
                            &extension->dlhandle);
                    if(result != GLOBUS_SUCCESS)
                    {
                        goto error_dll;
                    }
                    
                    result =
                       globus_l_extension_get_module(
                           extension->dlhandle,
                           extension_name,
                           &extension->module);

                }
#               else
                {
                    globus_assert(BUILD_STATIC_ONLY == 0);
                    result = globus_error_put(
                        globus_error_construct_error(
                            GLOBUS_EXTENSION_MODULE,
                            NULL,
                            GLOBUS_EXTENSION_ERROR_OPEN_FAILED,
                            __FILE__,
                            _globus_func_name,
                            __LINE__,
                            "No support for dynamically loading %s\n",
                            extension->name));
                }
#               endif /* !defined(BUILD_STATIC_ONLY) */

                if(result != GLOBUS_SUCCESS)
                {
                    goto error_module;
                }
            }
            
            globus_hashtable_insert(
                &globus_l_extension_loaded,
                extension->name,
                extension);
                
            last_extension = (globus_l_extension_module_t *)
                globus_thread_getspecific(globus_l_extension_owner_key);
            globus_thread_setspecific(globus_l_extension_owner_key, extension);
            
#if USE_SYMBOL_LABELS
            {
                int pre_warned = WARNING_USING_MIXED_THREAD_MODELS;
#endif
            rc = globus_module_activate_proxy(
                extension->module,
                globus_l_extension_deactivate_proxy,
                extension);
#if USE_SYMBOL_LABELS
                if ((!pre_warned) && WARNING_USING_MIXED_THREAD_MODELS)
                {
                    GlobusExtensionDebugPrintf(
                        GLOBUS_L_EXTENSION_DEBUG_VERBOSE,
                        (_GCSL("[%s] Warning: extension %s was compiled with pthreads for GT 5.0.x and may not work correctly\n"),
                            _globus_func_name,
                            extension->name));

                }
            }
#endif
            
            globus_thread_setspecific(
                globus_l_extension_owner_key, last_extension);
            if(rc != GLOBUS_SUCCESS)
            {
                goto error_activate;
            }
        }
        else
        {
            extension->module_ref++;
            extension->ref++;
        }
    }
    globus_rmutex_unlock(&globus_l_extension_mutex);
    
    GlobusExtensionDebugExit();
    return GLOBUS_SUCCESS;

error_activate:
    globus_hashtable_remove(
        &globus_l_extension_loaded, extension->name);
    if(builtin && builtin->owner)
    {
        builtin->owner->ref--;
    }
error_module:
#ifndef BUILD_STATIC_ONLY
    if(extension->dlhandle)
    {
        lt_dlclose(extension->dlhandle);
    }
error_dll:
#endif /* !BUILD_STATIC_ONLY */
    globus_free(extension->name);
error_strdup:
    globus_free(extension);
error_alloc:
    globus_rmutex_unlock(&globus_l_extension_mutex);
error_param:
    GlobusExtensionDebugExitWithError();
    return result;
}
globus_result_t
globus_gridftp_server_control_attr_add_send(
    globus_gridftp_server_control_attr_t    in_attr,
    const char *                            module_name,
    globus_gridftp_server_control_transfer_cb_t send_cb,
    void *                                  user_arg)
{
    globus_i_gsc_module_func_t *            mod_func;
    globus_i_gsc_attr_t *                   attr;
    globus_result_t                         res;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_add_send);

    GlobusGridFTPServerDebugEnter();

    if(in_attr == NULL)
    {
        res = GlobusGridFTPServerErrorParameter("in_attr");
        goto err;
    }
    attr = in_attr;

    if(send_cb == NULL)
    {
        res = GlobusGridFTPServerErrorParameter("send_cb");
        goto err;
    }

    if(attr->version_ctl != GLOBUS_GRIDFTP_VERSION_CTL)
    {
        res = GlobusGridFTPServerErrorParameter("in_attr");
        goto err;
    }

    if(module_name == NULL)
    {
        attr->funcs.default_send_cb = send_cb;
        attr->funcs.default_send_arg = user_arg;
    }
    else
    {
        mod_func = (globus_i_gsc_module_func_t *) globus_malloc(
            sizeof(globus_i_gsc_module_func_t));
        if(mod_func == NULL)
        {
            res = GlobusGridFTPServerControlErrorSytem();
            goto err;
        }
        mod_func->func = send_cb;
        mod_func->user_arg = user_arg;
        mod_func->key = globus_libc_strdup(module_name);
        globus_hashtable_insert(
            &attr->funcs.send_cb_table,
            (void *)mod_func->key,
            mod_func);
    }
    GlobusGridFTPServerDebugExit();

    return GLOBUS_SUCCESS;

  err:

    GlobusGridFTPServerDebugExitWithError();

    return res;
}
/*
 * globus_l_module_increment()
 */
static globus_bool_t
globus_l_module_increment(
    globus_module_descriptor_t *	module_descriptor,
    globus_l_module_key_t		parent_key,
    globus_module_deactivate_proxy_cb_t deactivate_cb,
    void *                              user_arg)
{
    globus_l_module_entry_t *		entry;
    
    entry =
	globus_hashtable_lookup(
	    &globus_l_module_table,
	    (void *) module_descriptor->activation_func);

    if (entry != GLOBUS_NULL)
    {
	/*
	 * The module has already been registered.  Increment its reference
	 * counter and add any new clients to the dependency list
	 */
	entry->reference_count++;
	if (parent_key != GLOBUS_NULL
	    && globus_list_search(entry->clients,
				  (void *) parent_key) == GLOBUS_NULL)
	{
	    globus_list_insert(&entry->clients, (void *) parent_key);
	}

	if(entry->reference_count == 1)
	{
	    entry->deactivate_cb = deactivate_cb;
	    entry->user_arg = user_arg;
	    return GLOBUS_TRUE;
	}
	else
	{
    	    return GLOBUS_FALSE;
	}
    }
    else
    {
	/*
	 * This is the first time this module has been registered.  Create a
	 * new entry in the modules table.
	 */
	entry = (globus_l_module_entry_t *)
	    globus_malloc(sizeof(globus_l_module_entry_t));
	globus_assert(entry != GLOBUS_NULL);

	entry->descriptor = module_descriptor;
	entry->reference_count = 1;
	entry->clients = GLOBUS_NULL;
	entry->deactivate_cb = deactivate_cb;
	entry->user_arg = user_arg;
	if (parent_key != GLOBUS_NULL)
	{
	    globus_list_insert(&entry->clients, (void *) parent_key);
	}
	
	globus_hashtable_insert(
	    &globus_l_module_table,
	    (void *) module_descriptor->activation_func,
	    entry);

	globus_list_insert(&globus_l_module_list, entry);
	
	return GLOBUS_TRUE;
    }
}
static
globus_result_t
globus_l_python_module(
    const globus_net_manager_attr_t    *attrs,
    globus_l_python_modref_t          **pymod)
{
    globus_result_t                     result = GLOBUS_SUCCESS;
    int                                 rc = 0;
    globus_l_python_modref_t           *modref = NULL;
    PyObject                           *pymodname = NULL;

    for (int i = 0; attrs != NULL && attrs[i].scope != NULL; i++)
    {
        if (strcmp(attrs[i].scope, "python") == 0)
        {
            if (strcmp(attrs[i].name, "pymod") == 0)
            {
                modref = globus_hashtable_lookup(
                    &globus_l_python_modules, attrs[i].value);
                if (!modref)
                {
                    modref = malloc(sizeof(globus_l_python_modref_t));
                    if (!modref)
                    {
                        result = GLOBUS_FAILURE;
                        goto modref_malloc_fail;
                    }
                    modref->key = strdup(attrs[i].value);
                    if (!modref->key)
                    {
                        result = GLOBUS_FAILURE;
                        goto strdup_modref_key_fail;
                    }
                    pymodname = PyString_FromString(modref->key);
                    if (!pymodname)
                    {
                        result = GLOBUS_FAILURE;
                        goto modref_key_to_pystring_fail;
                    }
                    modref->module = PyImport_Import(pymodname);
                    if (!modref->module)
                    {
                        result = GLOBUS_FAILURE;
                        goto module_import_fail;
                    }
                    modref->pre_listen = globus_l_python_resolve_func(
                            modref->module, "pre_listen");
                    modref->post_listen = globus_l_python_resolve_func(
                            modref->module, "post_listen"); 
                    modref->end_listen = globus_l_python_resolve_func(
                            modref->module, "end_listen"); 
                    modref->pre_accept = globus_l_python_resolve_func(
                            modref->module, "pre_accept"); 
                    modref->post_accept = globus_l_python_resolve_func(
                            modref->module, "post_accept"); 
                    modref->pre_connect = globus_l_python_resolve_func(
                            modref->module, "pre_connect"); 
                    modref->post_connect = globus_l_python_resolve_func(
                            modref->module, "post_connect"); 
                    modref->pre_close = globus_l_python_resolve_func(
                            modref->module, "pre_close"); 
                    modref->post_close = globus_l_python_resolve_func(
                            modref->module, "post_close"); 

                    rc = globus_hashtable_insert(
                            &globus_l_python_modules,
                            modref->key,
                            modref);
                    if (rc != GLOBUS_SUCCESS)
                    {
                        result = GLOBUS_FAILURE;
                        goto hashtable_insert_fail;
                    }
                }
                Py_XDECREF(pymodname);
                break;
            }
        }
    }
hashtable_insert_fail:
    if (result != GLOBUS_SUCCESS)
    {
        Py_XDECREF(modref->pre_listen);
        Py_XDECREF(modref->post_listen);
        Py_XDECREF(modref->end_listen);
        Py_XDECREF(modref->pre_accept);
        Py_XDECREF(modref->post_accept);
        Py_XDECREF(modref->pre_connect);
        Py_XDECREF(modref->post_connect);
        Py_XDECREF(modref->pre_close);
        Py_XDECREF(modref->post_close);
        Py_XDECREF(modref->module);
    }
module_import_fail:
modref_key_to_pystring_fail:
    if (result != GLOBUS_SUCCESS)
    {
        free(modref->key);
strdup_modref_key_fail:
        free(modref);
        modref = NULL;
    }
modref_malloc_fail:
    *pymod = modref;
    return result;
}
static
FILE *
globus_l_net_manager_logging_get_logfile(
    const globus_net_manager_attr_t    *attrs)
{
    int                                 rc = 0;
    FILE *                              handle = NULL;
    globus_l_nm_logging_logref_t *      logref = NULL;

    for (int i = 0; attrs != NULL && attrs[i].scope != NULL; i++)
    {
        if (strcmp(attrs[i].scope, "logging") == 0)
        {
            if (strcmp(attrs[i].name, "file") == 0)
            {
                logref = globus_hashtable_lookup(
                    &globus_l_nm_logging_logfiles, attrs[i].value);
                if (!logref)
                {
                    handle = fopen(attrs[i].value, "a");
                    if (!handle)
                    {
                        goto fopen_fail;
                    }
                    logref = malloc(sizeof(globus_l_nm_logging_logref_t));
                    if (logref == NULL)
                    {
                        goto logref_malloc_fail;
                    }
                    logref->key = strdup(attrs[i].value);
                    if (logref->key == NULL)
                    {
                        goto logref_key_fail;
                    }
                    logref->handle = handle;
                    handle = NULL;
                    rc = globus_hashtable_insert(
                            &globus_l_nm_logging_logfiles,
                            logref->key,
                            logref);
                    if (rc != GLOBUS_SUCCESS)
                    {
                        goto hashtable_insert_fail;
                    }
                }
                break;
            }
        }
    }

    return logref ? logref->handle : stdout;

hashtable_insert_fail:
logref_key_fail:
logref_malloc_fail:
    if (handle)
    {
        fclose(handle);
        handle = NULL;
    }
fopen_fail:
    if (logref)
    {
        free(logref->key);
        free(logref);
        logref = NULL;
    }
    return stdout;
}