globus_result_t
globus_xio_attr_init(
    globus_xio_attr_t *                 attr)
{
    globus_result_t                     res;
    globus_i_xio_attr_t *               xio_attr;
    GlobusXIOName(globus_xio_attr_init);

    GlobusXIODebugEnter();
    
    if(attr == NULL)
    {
        res = GlobusXIOErrorParameter("attr");
        goto err;
    }
   
    /* allocate the attr */ 
    xio_attr = (globus_i_xio_attr_t *)
                globus_calloc(sizeof(globus_i_xio_attr_t), 1);
    if(xio_attr == NULL)
    {
        res = GlobusXIOErrorMemory("attr");
        goto err;
    }

    xio_attr->entry = (globus_i_xio_attr_ent_t *)
        globus_calloc(sizeof(globus_i_xio_attr_ent_t) *
            GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE, 1);
    if(xio_attr->entry == NULL)
    {
        *attr = GLOBUS_NULL;
        globus_free(xio_attr);
        res = GlobusXIOErrorMemory("attr->entry");
        goto err;
    }

    /* zero it out */
    xio_attr->max = GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE;
    xio_attr->space = GLOBUS_CALLBACK_GLOBAL_SPACE;
    
    globus_mutex_lock(&globus_i_xio_mutex);
    {
        globus_list_insert(&globus_i_xio_outstanding_attrs_list, xio_attr);
    }
    globus_mutex_unlock(&globus_i_xio_mutex);
    
    *attr = xio_attr;

    GlobusXIODebugExit();
    return GLOBUS_SUCCESS;

  err:

    GlobusXIODebugExitWithError();
    return res;
}
static
globus_result_t
globus_l_xio_wrapblock_open(
    const globus_xio_contact_t *        contact_info,
    void *                              driver_link,
    void *                              driver_attr,
    globus_xio_operation_t              op)
{
    globus_result_t                     result;
    xio_l_wrapblock_wrapper_t *         wrapper;
    xio_l_wrapblock_handle_t *          wrapblock_handle;
    globus_xio_driver_t                 driver;
    globus_i_xio_op_t *                 xio_op;

    xio_op = (globus_i_xio_op_t *) op;
    driver = xio_op->_op_context->entry[op->ndx - 1].driver;

    wrapblock_handle = globus_calloc(1, sizeof(xio_l_wrapblock_handle_t));
    wrapblock_handle->wrapblock_driver = driver->wrap_data;

    if(globus_xio_driver_operation_is_blocking(op))
    {
        result = wrapblock_handle->wrapblock_driver->open_func(
            contact_info,
            driver_link,
            driver_attr,
            &wrapblock_handle->driver_handle);

        globus_xio_driver_finished_open(wrapblock_handle, op, result);
    }
    else
    {
        wrapper = (xio_l_wrapblock_wrapper_t *)
            globus_calloc(1, sizeof(xio_l_wrapblock_wrapper_t));
        wrapper->wrapblock_handle = wrapblock_handle;
        wrapper->link = driver_link;
        wrapper->op = op;
        wrapper->driver = driver;

        if(driver_attr != NULL && driver->attr_copy_func != NULL)
        {
            driver->attr_copy_func(&wrapper->attr, driver_attr);
        }
        /* gotta copy contact info the hard way */
        globus_xio_contact_copy(&wrapper->ci, contact_info);

        globus_callback_register_oneshot(
            NULL,
            NULL,
            globus_l_xio_wrapblock_open_kickout,
            wrapper);
    }

    return GLOBUS_SUCCESS;
}
/*
 *  copy an attribute structure
 */
static
globus_result_t
globus_l_xio_popen_attr_copy(
    void **                             dst,
    void *                              src)
{
    xio_l_popen_attr_t *                attr;
    xio_l_popen_attr_t *                src_attr;
    globus_result_t                     result;
    int                                 i;
    GlobusXIOName(globus_l_xio_popen_attr_copy);

    GlobusXIOPOpenDebugEnter();

    src_attr = (xio_l_popen_attr_t *) src;
    attr = (xio_l_popen_attr_t *) globus_malloc(sizeof(xio_l_popen_attr_t));
    if(!attr)
    {
        result = GlobusXIOErrorMemory("attr");
        goto error_attr;
    }

    memcpy(attr, src_attr, sizeof(xio_l_popen_attr_t));
    if(src_attr->program_name != NULL)
    {
        attr->program_name = strdup(src_attr->program_name);
    }
    if(src_attr->argc > 0)
    {
        attr->argv = (char **)globus_calloc(attr->argc+1, sizeof(char*));
        for(i = 0; i < attr->argc; i++)
        {
            attr->argv[i] = strdup(src_attr->argv[i]);
        }
        attr->argv[i] = NULL;
    }
    if(src_attr->env_count > 0)
    {
        attr->env = (char **)globus_calloc(attr->env_count+1, sizeof(char*));
        for(i = 0; i < attr->env_count; i++)
        {
            attr->env[i] = strdup(src_attr->env[i]);
        }
        attr->env[i] = NULL;
    }
    *dst = attr;

    GlobusXIOPOpenDebugExit();
    return GLOBUS_SUCCESS;

error_attr:
    GlobusXIOPOpenDebugExitWithError();
    return result;
}
globus_result_t
gfs_i_xio_cp_start(
    gfs_i_xio_cp_handle_t **            cp_h_out,
    globus_fifo_t *                     read_handle_fifo,
    globus_fifo_t *                     write_handle_fifo,
    globus_callback_func_t              complete_cb,
    globus_callback_func_t              update_cb,
    void *                              user_arg)
{
    globus_fifo_t *                     read_q;
    gfs_i_xio_cp_handle_t *             cp_h;

    cp_h = (gfs_i_xio_cp_handle_t *)
        globus_calloc(1, sizeof(gfs_i_xio_cp_handle_t));
    cp_h->read_all_q = globus_fifo_copy(net_handle_fifo);
    cp_h->write_all_q = globus_fifo_copy(net_handle_fifo);
    cp_h->write_q = globus_fifo_copy(net_handle_fifo);
    globus_fifo_init(&cp_h->read_buffer_q);
    cp_h->block_size = block_size;
    cp_h->cb = complete_cb;
    cp_h->user_arg = user_arg;
    globus_mutex_init(&cp_h->mutex, NULL);
    cp_h->state = GFS_XIO_CP_STATE_OPEN;
    read_q = globus_fifo_copy(net_handle_fifo);

    cp_h->read_handle_count = globus_fifo_size(cp_h->read_all_q);
    cp_h->write_handle_count = globus_fifo_size(cp_h->write_all_q);

    *cp_h_out = cp_h;

    globus_mutex_lock(&cp_h->mutex);
    {
        while(!globus_fifo_empty(read_q))
        {
            xio_h = (globus_xio_handle_t) globus_fifo_dequeue(cp_h->read_q);

            read_buf = (gfs_l_xio_read_buffer_t *)
                globus_calloc(sizeof(gfs_l_xio_read_buffer_t)+block_size, 1);
            read_buf->block_size = block_size;
            read_buf->whos_my_daddy = cp_h;

            gfs_l_xio_cp_post_read(xio_h, read_buf);
        }
    }
    globus_mutex_unlock(&cp_h->mutex);

    globus_fifo_destroy(read_q);

    return GLOBUS_SUCCESS;
}
static
globus_result_t
globus_l_xio_wrapblock_read(
    void *                              driver_specific_handle,
    const globus_xio_iovec_t *          iovec,
    int                                 iovec_count,
    globus_xio_operation_t              op)
{
    globus_size_t                       nbytes;
    globus_result_t                     result;
    int                                 i;
    xio_l_wrapblock_wrapper_t *         wrapper;
    xio_l_wrapblock_handle_t *          wrapblock_handle;

    wrapblock_handle = (xio_l_wrapblock_handle_t *) driver_specific_handle;
    if(globus_xio_driver_operation_is_blocking(op))
    {
        result = wrapblock_handle->wrapblock_driver->read_func(
            wrapblock_handle->driver_handle,
            iovec,
            iovec_count,
            &nbytes);
        globus_xio_driver_finished_read(op, result, nbytes);
    }
    else
    {
        wrapper = (xio_l_wrapblock_wrapper_t *)
            globus_calloc(1, sizeof(xio_l_wrapblock_wrapper_t));
        wrapper->iovec = (globus_xio_iovec_t *)
            globus_calloc(iovec_count, sizeof(globus_xio_iovec_t));
        wrapper->iovec_count = iovec_count;
        wrapper->op = op;
        wrapper->wrapblock_handle = driver_specific_handle;

        for(i = 0; i < iovec_count; i++)
        {
            wrapper->iovec[i].iov_base = iovec[i].iov_base;
            wrapper->iovec[i].iov_len = iovec[i].iov_len;
        }

        globus_callback_register_oneshot(
            NULL,
            NULL,
            globus_l_xio_wrapblock_read_kickout,
            wrapper);
    }
    return GLOBUS_SUCCESS;
}
static
globus_result_t
globus_l_xio_pipe_handle_init(
    xio_l_pipe_handle_t **              handle,
    xio_l_pipe_attr_t *                 attr)
{
    globus_result_t                     result;
    GlobusXIOName(globus_l_xio_pipe_handle_init);
    
    GlobusXIOPipeDebugEnter();
    
    *handle = (xio_l_pipe_handle_t *)
        globus_calloc(1, sizeof(xio_l_pipe_handle_t));
    if(!*handle)
    {
        result = GlobusXIOErrorMemory("handle");
        goto error_handle;
    }
    
    globus_mutex_init(&(*handle)->lock, NULL);
    (*handle)->use_blocking_io = attr->use_blocking_io;
    (*handle)->infd = attr->infd;
    (*handle)->outfd = attr->outfd;

    GlobusXIOPipeDebugExit();
    return GLOBUS_SUCCESS;

error_handle:
    GlobusXIOPipeDebugExitWithError();
    return result;    
}
static
globus_result_t
globus_l_xio_wrapblock_server_accept(
    void *                              driver_server,
    globus_xio_operation_t              op)
{
    xio_l_wrapblock_wrapper_t *         wrapper;
    globus_xio_driver_t                 driver;
    globus_i_xio_op_t *                 xio_op;

    xio_op = (globus_i_xio_op_t *) op;
    driver = xio_op->_op_server->entry[op->ndx - 1].driver;

    wrapper = (xio_l_wrapblock_wrapper_t *)
        globus_calloc(1, sizeof(xio_l_wrapblock_wrapper_t));
    wrapper->wrapblock_driver = driver->wrap_data;
    wrapper->attr = driver_server;
    wrapper->op = op;

    globus_callback_register_oneshot(
        NULL,
        NULL,
        globus_l_xio_wrapblock_accept_kickout,
        wrapper);

    return GLOBUS_SUCCESS;
}
globus_result_t
list_init(list_t ** List)
{
	globus_result_t result = GLOBUS_SUCCESS;

	GlobusGFSName(__func__);
	GlobusGFSHpssDebugEnter();

	/* Allocate the list. */
	*List = (list_t *) globus_calloc(1, sizeof(list_t));
	if (*List == NULL)
	{
		result = GlobusGFSErrorMemory("list_t");
		goto cleanup;
	}

	/* Initialize the list. */
	globus_mutex_init(&(*List)->Lock, NULL);

cleanup:
	if (result != GLOBUS_SUCCESS)
	{
		GlobusGFSHpssDebugExitWithError();
		return result;
	}

	GlobusGFSHpssDebugExit();
	return SUCCESS;
}
static
globus_result_t
globus_l_xio_popen_handle_init(
    xio_l_popen_handle_t **             handle)
{
    globus_result_t                     result;
    GlobusXIOName(globus_l_xio_popen_handle_init);
    
    GlobusXIOPOpenDebugEnter();
    
    *handle = (xio_l_popen_handle_t *)
        globus_calloc(1, sizeof(xio_l_popen_handle_t));
    if(!*handle)
    {
        result = GlobusXIOErrorMemory("handle");
        goto error_handle;
    }
    
    globus_mutex_init(&(*handle)->lock, NULL);
    
    GlobusXIOPOpenDebugExit();
    return GLOBUS_SUCCESS;

error_handle:
    GlobusXIOPOpenDebugExitWithError();
    return result;    
}
globus_result_t
list_insert_before(list_t * List,
                   void   * NewData,
                   void   * ExistingData)
{
	entry_t         * new_entry      = NULL;
	entry_t         * existing_entry = NULL;
	globus_result_t   result         = GLOBUS_SUCCESS;

	GlobusGFSName(__func__);
	GlobusGFSHpssDebugEnter();

	/* Allocate the new entry. */
	new_entry = (entry_t *) globus_calloc(1, sizeof(entry_t));
	if (new_entry == NULL)
	{
		result = GlobusGFSErrorMemory("entry_t");
		goto cleanup;
	}

	/* Save the new entry's data. */
	new_entry->Data = NewData;

	/* Now put it on the list. */
	globus_mutex_lock(&List->Lock);
	{
		/* Find the existing entry. */
		for (existing_entry  = List->Head; 
		     existing_entry != NULL; 
		     existing_entry  = existing_entry->Next)
		{
			if (existing_entry->Data == ExistingData)
				break;
		}

		/* Make sure we found something. */
		globus_assert(existing_entry != NULL);

		/* Insert before the existing entry. */
		new_entry->Prev      = existing_entry->Prev;
		existing_entry->Prev = new_entry;
		new_entry->Next      = existing_entry;
		if (new_entry->Prev == NULL)
			List->Head = new_entry;
		else
			new_entry->Prev->Next = new_entry;
	}
	globus_mutex_unlock(&List->Lock);

cleanup:
	if (result != GLOBUS_SUCCESS)
	{
		GlobusGFSHpssDebugExitWithError();
		return result;
	}

	GlobusGFSHpssDebugExit();
	return SUCCESS;
}
static 
globus_result_t
globus_l_net_manager_context_load_entry(
    const char *                            name,
    globus_i_net_manager_context_entry_t ** entry)
{
    globus_extension_handle_t               ext_handle;
    globus_net_manager_t *                  loaded_manager;
    char *                                  dll_name = NULL;
    globus_i_net_manager_context_entry_t *  ent;
    int                                     rc;
    globus_result_t                         result = GLOBUS_SUCCESS;
    GlobusNetManagerName(globus_l_net_manager_context_load_entry);

    /* is module already in registry? */
    loaded_manager = (globus_net_manager_t *) globus_extension_lookup(
        &ext_handle, GLOBUS_NET_MANAGER_REGISTRY, (void *) name);
    if(loaded_manager == NULL)
    {
        /* load and activate the dll */
        dll_name = globus_common_create_string(
            "globus_net_manager_%s", name);

        rc = globus_extension_activate(dll_name);        
        if(rc != GLOBUS_SUCCESS)
        {
            result = GlobusNetManagerErrorManager(
                rc, name, "attempting to activate module.");
            goto error_activate;
        }
    
        /* now module should be in registry */
        loaded_manager = (globus_net_manager_t *) globus_extension_lookup(
            &ext_handle, GLOBUS_NET_MANAGER_REGISTRY, (void *) name);
        if(loaded_manager == NULL)
        {
            result = GlobusNetManagerErrorManager(
                rc, name, "attempting to load activated module.");
            goto error_activate;
        }
    }
    ent = globus_calloc(1, sizeof(globus_i_net_manager_context_entry_t));
    ent->manager = loaded_manager;
    ent->ext_handle = ext_handle;
    ent->name = strdup(name);
    ent->dll_name = dll_name;
    
    *entry = ent;
    return GLOBUS_SUCCESS;
    
error_activate:
    globus_free(dll_name);
    *entry = NULL;
    return result;
}
globus_result_t
globus_gridftp_server_control_attr_init(
    globus_gridftp_server_control_attr_t *  in_attr)
{
    globus_i_gsc_attr_t *                   attr;
    globus_result_t                         res;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_init);

    GlobusGridFTPServerDebugEnter();

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

    attr = (globus_i_gsc_attr_t *) globus_calloc(
                1, sizeof(globus_i_gsc_attr_t));
    if(attr == NULL)
    {
        res = GlobusGridFTPServerControlErrorSytem();
        goto err;
    }

    globus_hashtable_init(
        &attr->funcs.send_cb_table,
        GLOBUS_GRIDFTP_SERVER_HASHTABLE_SIZE,
        globus_hashtable_string_hash,
        globus_hashtable_string_keyeq);

    globus_hashtable_init(
        &attr->funcs.recv_cb_table,
        GLOBUS_GRIDFTP_SERVER_HASHTABLE_SIZE,
        globus_hashtable_string_hash,
        globus_hashtable_string_keyeq);

    attr->funcs.resource_cb = NULL;
    attr->version_ctl = GLOBUS_GRIDFTP_VERSION_CTL;
    attr->modes = globus_libc_strdup("ES");
    attr->types = globus_libc_strdup("AI");
    attr->base_dir = globus_libc_strdup("/");

    *in_attr = attr;

    GlobusGridFTPServerDebugExit();

    return GLOBUS_SUCCESS;

  err:

    GlobusGridFTPServerDebugExitWithError();

    return res;
}
globus_result_t
globus_xio_stack_copy(
    globus_xio_stack_t *                dst,
    globus_xio_stack_t                  src)
{
    globus_i_xio_stack_t *		xio_stack_src;
    globus_i_xio_stack_t *		xio_stack_dst;
    globus_result_t                     res;
    GlobusXIOName(globus_xio_stack_push_driver);
                    
    GlobusXIODebugEnter();
    if(dst == NULL)
    {
        res = GlobusXIOErrorParameter("dst");
        goto err;
    }

    if(src == NULL)
    {
        res = GlobusXIOErrorParameter("src");
        goto err;
    }

    xio_stack_src = src;

    xio_stack_dst = (globus_i_xio_stack_t *)
        globus_calloc(1, sizeof(globus_i_xio_stack_t));

    /* check for memory alloc failure */
    if(xio_stack_dst == NULL)
    {
        res = GlobusXIOErrorMemory("xio_stack_dst");
        goto err;
    }

    xio_stack_dst->size = xio_stack_src->size;
    xio_stack_dst->driver_stack = globus_list_copy(
					xio_stack_src->driver_stack);
    *dst = xio_stack_dst;

    GlobusXIODebugExit();

    return GLOBUS_SUCCESS;

  err:

    GlobusXIODebugExitWithError();
    return res;
}
globus_result_t
globus_xio_driver_list_create_ent(
    const char *                        driver_desc,
    globus_xio_driver_t                 driver_in,
    globus_bool_t                       load,
    globus_xio_driver_list_ent_t **     ent_out)
{   
    globus_xio_driver_t                 driver;
    globus_xio_driver_list_ent_t *      list_ent;
    char *                              driver_name;
    char *                              opts;
    globus_result_t                     result;

    driver_name = strdup(driver_desc);
    opts = strchr(driver_name, ':');
    if(opts != NULL)
    {
        *opts = '\0';
        opts++; 
    }

    if(load)
    {
        result = globus_xio_driver_load(driver_name, &driver);
        if(result != GLOBUS_SUCCESS)
        {
            goto error_load;
        }
    }
    else
    {
        driver = driver_in;
    }

    list_ent = (globus_xio_driver_list_ent_t *)
        globus_calloc(1, sizeof(globus_xio_driver_list_ent_t));
    list_ent->opts = globus_libc_strdup(opts);
    list_ent->driver = driver;
    list_ent->driver_name = driver_name;
    list_ent->loaded = load;

    *ent_out = list_ent;

    return GLOBUS_SUCCESS;

error_load:
    globus_free(driver_name);
    return result;
}   
static globus_result_t
transfer_control_common_init(transfer_control_msg_type_t    OpType,
                             msg_handle_t                *  MsgHandle,
                             transfer_control_t          ** TransferControl)
{
	globus_result_t result = GLOBUS_SUCCESS;

	GlobusGFSName(__func__);
	GlobusGFSHpssDebugEnter();

	/* Allocate the handle. */
	*TransferControl = (transfer_control_t *) globus_calloc(1, sizeof(transfer_control_t));
	if (*TransferControl == NULL)
	{
		result = GlobusGFSErrorMemory("transfer_control_t");
		goto cleanup;
	}

	/* Initialize the entries. */
	globus_mutex_init(&(*TransferControl)->Lock, NULL);
	(*TransferControl)->OpType        = OpType;
	(*TransferControl)->MsgHandle     = MsgHandle;
	(*TransferControl)->State         = TRANSFER_CONTROL_WAIT_FOR_DATA_READY;
	(*TransferControl)->MsgRegisterID = MSG_REGISTER_ID_NONE;

	/* Intialize the range list. Fill it later. */
	result = range_list_init(&(*TransferControl)->TransferRangeList);
	if (result != GLOBUS_SUCCESS)
		goto cleanup;

	/* Register to receive messages. */
	result = msg_register(MsgHandle,
	                      MSG_COMP_ID_IPC_CONTROL,
	                      MSG_COMP_ID_TRANSFER_CONTROL,
	                      transfer_control_msg_recv,
	                      *TransferControl,
	                      &(*TransferControl)->MsgRegisterID);

cleanup:
    if (result != GLOBUS_SUCCESS)
    {
        GlobusGFSHpssDebugExitWithError();
        return result;
    }

    GlobusGFSHpssDebugExit();
    return GLOBUS_SUCCESS;
}
/*
 * This is the basic (minimal) initialization, used at the start of
 * all sessions.
 */
globus_result_t
session_init(globus_gfs_session_info_t *  SessionInfo,
             session_handle_t          ** SessionHandle)
{
	globus_result_t result = GLOBUS_SUCCESS;

    GlobusGFSName(__func__);
    GlobusGFSHpssDebugEnter();

	/* Allocate our session handle. */
	*SessionHandle = (session_handle_t *) globus_calloc(1, sizeof(session_handle_t));
	if (*SessionHandle == NULL)
	{
		result = GlobusGFSErrorMemory("session handle");
		goto cleanup;
	}

	/*
	 * Copy out the session info.
	 */
	result = session_copy_session_info(SessionInfo, &(*SessionHandle)->SessionInfo);
	if (result != GLOBUS_SUCCESS)
		goto cleanup;

	/* Indicate that no authentication has occurred. */
	(*SessionHandle)->Authenticated = GLOBUS_FALSE;

	/*
	 * Initialize the preferences.
	 */
	(*SessionHandle)->Pref.CosID    = SESSION_NO_COS_ID;
	(*SessionHandle)->Pref.FamilyID = SESSION_NO_FAMILY_ID;

cleanup:
	if (result != GLOBUS_SUCCESS)
	{
		/* Destroy the session handle. */
		session_destroy(*SessionHandle);
		/* Release our handle */
		*SessionHandle = NULL;

		GlobusGFSHpssDebugExitWithError();
		return result;
	}

	GlobusGFSHpssDebugExit();
	return GLOBUS_SUCCESS;
}
globus_result_t
globus_xio_wrapblock_init(
    globus_xio_driver_t                 driver,
    globus_xio_wrapblock_open_func_t    open_func,
    globus_xio_wrapblock_close_func_t   close_func,
    globus_xio_wrapblock_read_func_t    read_func,
    globus_xio_wrapblock_write_func_t   write_func,
    globus_xio_wrapblock_accept_func_t  accept_func)
{
    xio_l_wrapblock_driver_t *          wrapblock_driver;

    if(open_func != NULL)
    {
        driver->transport_open_func = globus_l_xio_wrapblock_open;
    }
    if(close_func != NULL)
    {
        driver->close_func = globus_l_xio_wrapblock_close;
    }
    if(read_func != NULL)
    {
        driver->read_func = globus_l_xio_wrapblock_read;
    }
    if(write_func != NULL)
    {
        driver->write_func = globus_l_xio_wrapblock_write;
    }
    if(accept_func != NULL)
    {
        driver->server_accept_func = globus_l_xio_wrapblock_server_accept;
    }

    wrapblock_driver = (xio_l_wrapblock_driver_t *)
        globus_calloc(1, sizeof(xio_l_wrapblock_driver_t));
    wrapblock_driver->open_func = open_func;
    wrapblock_driver->close_func = close_func;
    wrapblock_driver->read_func = read_func;
    wrapblock_driver->write_func = write_func;
    wrapblock_driver->accept_func = accept_func;
    
    driver->wrap_data = wrapblock_driver;

    return GLOBUS_SUCCESS;
}
globus_result_t
list_insert(list_t * List,
            void   * Data)
{
	entry_t         * entry  = NULL;
	globus_result_t   result = GLOBUS_SUCCESS;

	GlobusGFSName(__func__);
	GlobusGFSHpssDebugEnter();

	/* Allocate the new entry. */
	entry = (entry_t *) globus_calloc(1, sizeof(entry_t));
	if (entry == NULL)
	{
		result = GlobusGFSErrorMemory("entry_t");
		goto cleanup;
	}

	/* Save the entry's data. */
	entry->Data = Data;

	/* Now put it on the list. */
	globus_mutex_lock(&List->Lock);
	{
		/* Let's insert on the tail assuming a FIFO usage. */
		entry->Prev = List->Tail;
		if (List->Tail != NULL)
			List->Tail->Next = entry;
		List->Tail = entry;
		if (List->Head == NULL)
			List->Head = entry;
	}
	globus_mutex_unlock(&List->Lock);

cleanup:
	if (result != GLOBUS_SUCCESS)
	{
		GlobusGFSHpssDebugExitWithError();
		return result;
	}

	GlobusGFSHpssDebugExit();
	return SUCCESS;
}
static
globus_result_t
globus_l_xio_win32_blocking_init(
    globus_l_xio_win32_blocking_info_t ** u_blocking_info)
{
    globus_l_xio_win32_blocking_info_t * blocking_info;
    globus_result_t                     result;
    GlobusXIOName(globus_l_xio_win32_blocking_init);
    
    GlobusXIOSystemDebugEnter();
    
    blocking_info = (globus_l_xio_win32_blocking_info_t *)
        globus_calloc(1, sizeof(globus_l_xio_win32_blocking_info_t));
    if(!blocking_info)
    {
        result = GlobusXIOErrorMemory("blocking_info");
        goto error_info;
    }
    
    blocking_info->event = CreateEvent(0, FALSE, FALSE, 0);
    if(blocking_info->event == 0)
    {
        result = GlobusXIOErrorSystemError(
            "CreateEvent", GetLastError());
        goto error_create;
    }
    
    *u_blocking_info = blocking_info;
    
    GlobusXIOSystemDebugExit();
    return GLOBUS_SUCCESS;

error_create:
    globus_free(blocking_info);
error_info:
    *u_blocking_info = 0;
    GlobusXIOSystemDebugExitWithError();
    return result;
}
static globus_result_t
globus_l_xio_telnet_attr_init(
    void **                             out_driver_attr)
{
    globus_l_xio_telnet_attr_t *        attr;
    globus_result_t                     res;
    GlobusXIOName(globus_l_xio_telnet_attr_init);
    
    attr = (globus_l_xio_telnet_attr_t *)
        globus_calloc(sizeof(globus_l_xio_telnet_attr_t), 1);
    if(!attr)
    {
        res = GlobusXIOErrorMemory("attr");
        goto error;
    }

    *out_driver_attr = attr;
    
    return GLOBUS_SUCCESS;

error:
    return res;
}
static
globus_result_t
globus_l_xio_wrapblock_close(
    void *                              driver_specific_handle,
    void *                              attr,
    globus_xio_operation_t              op)
{
    globus_result_t                     result;
    xio_l_wrapblock_wrapper_t *         wrapper;
    xio_l_wrapblock_handle_t *          wrapblock_handle;

    wrapblock_handle = (xio_l_wrapblock_handle_t *) driver_specific_handle;
    if(globus_xio_driver_operation_is_blocking(op))
    {
        result = wrapblock_handle->wrapblock_driver->close_func(
            wrapblock_handle->driver_handle,
            attr);
        globus_xio_driver_finished_close(op, result);
        globus_free(wrapblock_handle);
    }
    else
    {
        wrapper = (xio_l_wrapblock_wrapper_t *)
            globus_calloc(1, sizeof(xio_l_wrapblock_wrapper_t));
        wrapper->attr = attr;
        wrapper->op = op;
        wrapper->wrapblock_handle = driver_specific_handle;

        globus_callback_register_oneshot(
            NULL,
            NULL,
            globus_l_xio_wrapblock_close_kickout,
            wrapper);
    }
    return GLOBUS_SUCCESS;
}
globus_result_t
globus_net_manager_context_init(
    globus_net_manager_context_t *      context,
    const globus_net_manager_attr_t *   attrs)
{
    globus_i_net_manager_context_t *    ctx;
    globus_net_manager_attr_t *         attr;
    globus_result_t                     result;
    int                                 i;
    int                                 j;
    int                                 max_attr_count;
    int                                 attrnum;
    char *                              current_scope = NULL;
    globus_i_net_manager_context_entry_t *  ent = NULL;
    GlobusNetManagerName(globus_net_manager_context_init);
    
    if(context == NULL || attrs == NULL || attrs[0].scope == NULL)
    {
        result = GlobusNetManagerErrorParameter("No parameter may be NULL.");
        goto error_no_attr;
    }
    
    ctx = globus_calloc(1, sizeof(globus_i_net_manager_context_t));
    if(ctx == NULL)
    {
        result = GlobusNetManagerErrorMemory("context");
        goto error_ctx_mem;
    }
    for(max_attr_count = 0; 
        attrs[max_attr_count].scope != NULL;
        max_attr_count++);
    
    for(i = 0; attrs[i].scope != NULL; i++)
    {
        /* start of a new manager entry */
        if(strcmp(attrs[i].scope, "net_manager") == 0 && 
            strcmp(attrs[i].name, "manager") == 0)
        {
            ent = NULL;
            attrnum = 0;
            current_scope = attrs[i].value;

            result = globus_l_net_manager_context_load_entry(
                attrs[i].value, &ent);
            if(result)
            {
                goto error_load;
            }

            ent->attrs = calloc(
                max_attr_count, sizeof(globus_net_manager_attr_t));
            for(j = 0; attrs[j].scope != NULL; j++)
            {
                if(strcmp(attrs[j].scope, "global") == 0)
                {
                    result = globus_net_manager_attr_init(
                            &ent->attrs[attrnum++],
                            attrs[j].scope,
                            attrs[j].name,
                            attrs[j].value);
                    if(result)
                    {
                        goto error_attr;
                    }
                }
            }
            ent->attrs[attrnum] = globus_net_manager_null_attr;
            
            globus_list_insert(&ctx->managers, ent);
        }
        /* attrs for the current manager entry */
        else if(current_scope && strcmp(attrs[i].scope, current_scope) == 0)
        {
            result = globus_net_manager_attr_init(
                    &ent->attrs[attrnum++],
                    attrs[i].scope,
                    attrs[i].name,
                    attrs[i].value);
            if(result)
            {
                goto error_attr;
            }
            ent->attrs[attrnum] = globus_net_manager_null_attr;
        }
        /* unrelated scope */
        else
        {
            ent = NULL;
            attrnum = 0;
            current_scope = attrs[i].value;
        }
    }
    
    *context = ctx;
    return GLOBUS_SUCCESS;
    
error_attr:
error_load:
    free(ctx);
error_ctx_mem:
error_no_attr:
    if (context)
    {
        *context = NULL;
    }

    return result;
}
globus_result_t
globus_xio_system_socket_init(
    globus_xio_system_socket_handle_t * uhandle,
    globus_xio_system_socket_t          socket,
    globus_xio_system_type_t            type)
{
    globus_result_t                     result;
    globus_l_xio_win32_socket_t *       handle;
    unsigned long                       flag;
    GlobusXIOName(globus_xio_system_socket_init);
    
    GlobusXIOSystemDebugEnterFD(socket);
    
    handle = (globus_l_xio_win32_socket_t *)
        globus_calloc(1, sizeof(globus_l_xio_win32_socket_t));
    if(!handle)
    {
        result = GlobusXIOErrorMemory("handle");
        goto error_alloc;
    }
    
    handle->socket = socket;
    win32_mutex_init(&handle->lock, 0);
    handle->ready_events = FD_READ; /* to avoid winsock fd_close bug */
    
    handle->event = WSACreateEvent();
    if(handle->event == 0)
    {
        result = GlobusXIOErrorSystemError(
            "WSACreateEvent", WSAGetLastError());
        goto error_create;
    }
    
    flag = 1;
    if(ioctlsocket(socket, FIONBIO, &flag) == SOCKET_ERROR)
    {
        result = GlobusXIOErrorSystemError(
            "ioctlsocket", WSAGetLastError());
        goto error_ioctl;
    }
    
    result = globus_i_xio_win32_event_register(
        &handle->event_entry,
        handle->event,
        globus_l_xio_win32_socket_event_cb,
        handle);
    if(result != GLOBUS_SUCCESS)
    {
        result = GlobusXIOErrorWrapFailed(
            "globus_i_xio_win32_event_register", result);
        goto error_register;
    }
    
    GlobusXIOSystemDebugPrintf(
        GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
        ("[%s] Registered event handle=%lu\n",
            _xio_name, (unsigned long) handle->event));
        
    *uhandle = handle;
    
    GlobusXIOSystemDebugExitFD(socket);
    return GLOBUS_SUCCESS;

error_register:
    flag = 0;
    ioctlsocket(socket, FIONBIO, &flag);
error_ioctl:
    WSACloseEvent(handle->event);
error_create:
    win32_mutex_destroy(&handle->lock);
    globus_free(handle);
error_alloc:
    GlobusXIOSystemDebugExitWithErrorFD(socket);
    return result;
}
globus_result_t
gridftp_init(gridftp_op_type_t             OpType,
	         globus_gfs_operation_t        Operation,
	         globus_gfs_transfer_info_t *  TransferInfo,
             buffer_handle_t            *  BufferHandle,
             msg_handle_t               *  MsgHandle,
             gridftp_eof_callback_t        EofCallbackFunc,
             void                       *  EofCallbackArg,
             gridftp_t                  ** GridFTP)
{
	globus_off_t    offset = 0;
	globus_off_t    length = 0;
	globus_result_t result = GLOBUS_SUCCESS;

	GlobusGFSName(__func__);
	GlobusGFSHpssDebugEnter();

	/* Allocate the handle. */
	*GridFTP = (gridftp_t *) globus_calloc(1, sizeof(gridftp_t));
	if (*GridFTP == NULL)
	{
		result = GlobusGFSErrorMemory("gridftp_t");
		goto cleanup;
	}

	/* Initialize the entries. */
	(*GridFTP)->OpType            = OpType;
	(*GridFTP)->Operation         = Operation;
	(*GridFTP)->BufferHandle      = BufferHandle;
	(*GridFTP)->MsgHandle         = MsgHandle;
	(*GridFTP)->EofCallbackFunc   = EofCallbackFunc;
	(*GridFTP)->EofCallbackArg    = EofCallbackArg;
	(*GridFTP)->EofCallbackCalled = GLOBUS_FALSE;
	(*GridFTP)->Eof               = GLOBUS_FALSE;
	(*GridFTP)->Stop              = GLOBUS_FALSE;
	(*GridFTP)->Result            = GLOBUS_SUCCESS;
	(*GridFTP)->OpCount           = 0;
	(*GridFTP)->PrivateBufferID   = buffer_create_private_list(BufferHandle);

	globus_mutex_init(&(*GridFTP)->Lock, NULL);
	globus_cond_init(&(*GridFTP)->Cond, NULL);

	/* On retrieves... */
	if (OpType == GRIDFTP_OP_TYPE_RETR)
	{
		/* Generate the stream range list. */
		result = range_list_init(&(*GridFTP)->StreamRanges);
		if (result != GLOBUS_SUCCESS)
			goto cleanup;

		/* Fill the range list. */
		result = range_list_fill_retr_range((*GridFTP)->StreamRanges, TransferInfo);
		if (result != GLOBUS_SUCCESS)
			goto cleanup;
	}

	/*
	 * We need to call the appropriate _get_read/write_range() function.
	 * It will setup Operation to return the correct file offsets. Without
	 * this call, our first read callback would always return 0 for streams mode
	 * regardless of REST commands. And since we can not tell streams mode from
	 * extended block mode, this is critical. We do not need to use offset or
	 * length; just making the call is good enough.
	 */
	switch (OpType)
	{
	case GRIDFTP_OP_TYPE_RETR:
		globus_gridftp_server_get_read_range(Operation, &offset, &length);
		break;
	case GRIDFTP_OP_TYPE_STOR:
		globus_gridftp_server_get_write_range(Operation, &offset, &length);
		break;
	}

cleanup:
	if (result != GLOBUS_SUCCESS)
	{
		GlobusGFSHpssDebugExitWithError();
		return result;
	}

	GlobusGFSHpssDebugExit();
	return GLOBUS_SUCCESS;
}
/**
 * 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*/
/**
 * 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_result_t
globus_l_gfork_send(
    gfork_i_lib_handle_t *              handle,
    uid_t                               pid,
    globus_xio_iovec_t *                iov,
    int                                 iovc,
    globus_xio_iovec_callback_t         cb,
    void *                              user_arg)
{
    int                                 i;
    globus_size_t                       nbytes;
    gfork_i_msg_t *                     msg;
    globus_result_t                     result = GLOBUS_SUCCESS;
    GForkFuncName(globus_l_gfork_send);

    if(handle->state != GFORK_STATE_OPEN)
    {
        return GForkErrorStr("Invalid state.  Is the handle already closed?");
    }
    msg = (gfork_i_msg_t *) globus_calloc(1, sizeof(gfork_i_msg_t));

    msg->header.from_pid = getpid();
    msg->header.to_pid = pid;
    msg->header.type = GLOBUS_GFORK_MSG_DATA;
    msg->lib_handle = handle;

    msg->user_arg = user_arg;

    msg->iov = (globus_xio_iovec_t *) globus_calloc(
                   iovc + 1, sizeof(globus_xio_iovec_t));
    msg->iov[0].iov_base = &msg->header;
    msg->iov[0].iov_len = sizeof(gfork_i_msg_header_t);

    nbytes = 0;
    for(i = 0; i < iovc; i++)
    {
        msg->iov[i+1].iov_base = iov[i].iov_base;
        msg->iov[i+1].iov_len = iov[i].iov_len;
        nbytes += iov[i].iov_len;
    }
    msg->client_cb = cb;
    msg->header.size = nbytes;

    nbytes += msg->iov[0].iov_len;

    msg->nbytes = nbytes;
    msg->iovc = iovc+1;
    if(!handle->writing)
    {
        handle->writing = GLOBUS_TRUE;
        result = globus_xio_register_writev(
                     handle->write_xio,
                     msg->iov,
                     msg->iovc,
                     msg->nbytes,
                     NULL,
                     gfork_l_client_writev_cb,
                     msg);
    }
    else
    {
        globus_fifo_enqueue(&handle->write_q, msg);
    }
    return result;
}
static
globus_result_t
globus_l_gfork_child_start(
    gfork_child_handle_t *              out_handle,
    const char *                        in_env_suffix,
    globus_gfork_open_func_t            open_cb,
    globus_gfork_closed_func_t          close_cb,
    globus_gfork_incoming_cb_t          incoming_cb,
    globus_gfork_error_func_t           error_cb,
    void *                              user_arg,
    globus_bool_t                       master)
{
    globus_result_t                     result;
    gfork_i_lib_handle_t *            handle;
    char *                              env;
    char *                              env_suffix;
    int                                 read_fd;
    int                                 write_fd;

    handle = (gfork_i_lib_handle_t *)
             globus_calloc(1, sizeof(gfork_i_lib_handle_t));

    handle->state = GFORK_STATE_OPEN;
    handle->open_cb = open_cb;
    handle->close_cb = close_cb;
    handle->error_cb = error_cb;
    handle->incoming_cb = incoming_cb;
    handle->user_arg = user_arg;
    handle->master = master;
    globus_mutex_init(&handle->mutex, NULL);
    globus_fifo_init(&handle->write_q);

    if(in_env_suffix == NULL)
    {
        env_suffix = "";
    }
    else
    {
        env_suffix = (char *) in_env_suffix;
    }
    env = globus_common_create_string("%s%s", GFORK_CHILD_READ_ENV, env_suffix);
    result = gfork_l_get_env_fd(env, &read_fd);

    globus_free(env);
    if(result != GLOBUS_SUCCESS)
    {
        goto error_read_env;
    }

    env = globus_common_create_string("%s%s",GFORK_CHILD_WRITE_ENV,env_suffix);
    result = gfork_l_get_env_fd(env, &write_fd);
    globus_free(env);
    if(result != GLOBUS_SUCCESS)
    {
        goto error_write_env;
    }

    result = gfork_i_make_xio_handle(&handle->read_xio, read_fd);
    if(result != GLOBUS_SUCCESS)
    {
        goto error_read_convert;
    }
    result = gfork_i_make_xio_handle(&handle->write_xio, write_fd);
    if(result != GLOBUS_SUCCESS)
    {
        goto error_write_convert;
    }

    globus_mutex_lock(&handle->mutex);
    {
        result = globus_xio_register_read(
                     handle->read_xio,
                     (globus_byte_t *)&handle->header,
                     sizeof(gfork_i_msg_header_t),
                     sizeof(gfork_i_msg_header_t),
                     NULL,
                     gfork_l_child_read_header_cb,
                     handle);
        if(result != GLOBUS_SUCCESS)
        {
            goto error_post;
        }
    }
    globus_mutex_unlock(&handle->mutex);

    *out_handle = handle;

    return GLOBUS_SUCCESS;

error_post:
    gfork_l_child_error(handle, result);
    globus_mutex_unlock(&handle->mutex);
error_write_convert:
    globus_xio_close(handle->read_xio, NULL);
error_read_convert:
error_write_env:
error_read_env:
    globus_fifo_destroy(&handle->write_q);
    globus_mutex_destroy(&handle->mutex);
    globus_free(handle);

    return result;
}
static globus_result_t
globus_l_xio_telnet_open(
    const globus_xio_contact_t *        contact_info,
    void *                              driver_link,
    void *                              driver_attr,
    globus_xio_operation_t              op)
{
    globus_result_t                     res;
    globus_l_xio_telnet_attr_t *       attr;
    globus_l_xio_telnet_handle_t *     handle;
    GlobusXIOName(globus_l_xio_telnet_open);

    /* decide what attr to use */
    if(driver_attr != NULL)
    {
        attr = (globus_l_xio_telnet_attr_t *) driver_attr;
    }
    else if(driver_link != NULL)
    {
        attr = (globus_l_xio_telnet_attr_t *) driver_link;
    }
    else
    {
        /* default */
        attr = NULL;
    }

    handle = (globus_l_xio_telnet_handle_t *) globus_calloc(
        sizeof(globus_l_xio_telnet_handle_t), 1);
    if(handle == NULL)
    {
        res = GlobusXIOErrorMemory("handle");
        goto error_handle_alloc;
    }

    if(attr != NULL && attr->force_server)
    {
        handle->client = GLOBUS_FALSE;
    }
    else
    {       
        handle->client = driver_link ? GLOBUS_FALSE : GLOBUS_TRUE;
    }

    handle->read_buffer_length = GLOBUS_L_XIO_TELNET_DEFAULT_BUFFER_SIZE;
    handle->read_buffer = globus_malloc(handle->read_buffer_length);
    if(handle->read_buffer == NULL)
    {
        res = GlobusXIOErrorMemory("buffer");
        goto error_buffer_alloc;
    }
    globus_mutex_init(&handle->mutex, NULL);
    globus_fifo_init(&handle->write_q);

    handle->create_buffer_mode = attr 
        ? attr->create_buffer_mode : GLOBUS_FALSE;

    res = globus_xio_driver_pass_open(
        op,
        contact_info,
        globus_l_xio_telnet_open_cb,
        handle);
    if(res != GLOBUS_SUCCESS)
    {
        goto error_pass;
    }

    return GLOBUS_SUCCESS;
error_pass:
    globus_free(handle->read_buffer);
    globus_mutex_destroy(&handle->mutex);
    globus_fifo_destroy(&handle->write_q);
error_buffer_alloc:
    globus_free(handle);
error_handle_alloc:
    return res;
}
/* driver list stuff */
globus_result_t
globus_xio_driver_list_from_string(
    char *                              driver_string,
    globus_list_t **                    driver_list,
    globus_hashtable_t *                safe_table)
{
    globus_result_t                     result;
    globus_bool_t                       done = GLOBUS_FALSE;
    globus_bool_t                       loaded;
    char *                              opts;
    char *                              ptr;
    char *                              driver_str;
    char *                              driver_name;
    char *                              tmp_str;
    globus_xio_driver_t                 driver;
    globus_list_t *                     list = NULL;
    globus_xio_driver_list_ent_t *      list_ent;
    GlobusXIOName(globus_xio_driver_list_from_string);

    *driver_list = NULL;

    if(driver_string == NULL) 
    {
        result = GlobusXIOErrorParameter("driver_string");
        goto error_param;
    }

    driver_str = globus_libc_strdup(driver_string);
    tmp_str = driver_str;
    while(!done)
    {
        loaded = GLOBUS_FALSE;
        driver_name = tmp_str;
        ptr = strchr(driver_name, ',');
        if(ptr != NULL)
        {
            *ptr = '\0';
            tmp_str = ptr+1;
        }
        else
        {
            done = GLOBUS_TRUE;
        }
        opts = strchr(driver_name, ':');
        if(opts != NULL)
        {
            *opts = '\0';
            opts++;

            /* decode the string */
            globus_url_string_hex_decode(opts);
        }

        /* check against the safe list */
        if(safe_table != NULL)
        {
            char *                      err_str;

            list_ent = (globus_xio_driver_list_ent_t *)
                globus_hashtable_lookup(safe_table, driver_name);

            if(list_ent == NULL)
            {
                err_str = globus_common_create_string(
                    "%s driver not whitelisted", driver_name);
                result = GlobusXIOErrorParameter(err_str);
                globus_free(err_str);
                goto error_load;
            }
            driver = list_ent->driver;
        }
        else
        {
            result = globus_xio_driver_load(driver_name, &driver);
            if(result != GLOBUS_SUCCESS)
            {
                goto error_load;
            }

            loaded = GLOBUS_TRUE;
        }

        list_ent = (globus_xio_driver_list_ent_t *)
            globus_calloc(1, sizeof(globus_xio_driver_list_ent_t));
        list_ent->opts = globus_libc_strdup(opts);
        list_ent->driver = driver;
        list_ent->driver_name = globus_libc_strdup(driver_name);
        list_ent->loaded = loaded;

        globus_list_insert(&list, list_ent);
    }

    globus_free(driver_str);

    /* reverse list */
    while(!globus_list_empty(list))
    {
        globus_list_insert(driver_list, globus_list_first(list));
        globus_list_remove(&list, list);
    }

    return GLOBUS_SUCCESS;

error_load:
    globus_free(driver_str);
    while(!globus_list_empty(list))
    {
        list_ent = (globus_xio_driver_list_ent_t *)
            globus_list_remove(&list, list);

        if(list_ent->loaded)
        {
            globus_xio_driver_unload(list_ent->driver);
        }
        globus_free(list_ent->driver_name);
        if(list_ent->opts != NULL)
        {
            globus_free(list_ent->opts);
        }
        globus_free(list_ent);
    }
error_param:
    return result;
}