globus_result_t
globus_gridftp_server_control_attr_set_log(
    globus_gridftp_server_control_attr_t    server_attr,
    globus_gridftp_server_control_log_cb_t  log_func,
    int                                     log_mask,
    void *                                  user_arg)
{
    globus_i_gsc_attr_t *                   attr;
    globus_result_t                         res;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_set_log);

    if(server_attr == NULL)
    {
        res = GlobusGridFTPServerErrorParameter("server_attr");
        goto err;
    }
    attr = (globus_i_gsc_attr_t *) server_attr;

    attr->funcs.log_func = log_func;
    attr->funcs.log_mask = log_mask;
    attr->funcs.log_arg = user_arg;

    return GLOBUS_SUCCESS;

  err:

    return res;
}
static void
globus_l_gsc_send_perf(
    globus_gridftp_server_control_op_t      op,
    int                                     stripe_ndx,
    int                                     stripe_count,
    globus_off_t                            nbytes)
{
    char *                                  msg;
    struct timeval                          now;
    GlobusGridFTPServerName(globus_l_gsc_send_perf);
                                                                                
    gettimeofday(&now, NULL);
    msg = globus_common_create_string(
        "112-Perf Marker\r\n"
        " Timestamp:  %ld.%01ld\r\n"
        " Stripe Index: %d\r\n"
        " Stripe Bytes Transferred: %"GLOBUS_OFF_T_FORMAT"\r\n"
        " Total Stripe Count: %d\r\n"
        "112 End.\r\n",
            now.tv_sec, now.tv_usec / 100000,
            stripe_ndx,
            nbytes,
            stripe_count);
    globus_i_gsc_intermediate_reply(op, msg);
    globus_free(msg);
}
globus_result_t
globus_gridftp_server_control_attr_data_functions(
    globus_gridftp_server_control_attr_t                server_attr,
    globus_gridftp_server_control_active_connect_cb_t   active_cb,
    void *                                              active_arg,
    globus_gridftp_server_control_passive_connect_cb_t  passive_cb,
    void *                                              passive_arg,
    globus_gridftp_server_control_data_destroy_cb_t     destroy_cb,
    void *                                              destroy_arg)
{
    globus_i_gsc_attr_t *                   attr;
    globus_result_t                         res;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_set_passive);

    if(server_attr == NULL)
    {
        res = GlobusGridFTPServerErrorParameter("server_attr");
        goto err;
    }
    attr = (globus_i_gsc_attr_t *) server_attr;

    attr->funcs.passive_cb = passive_cb;
    attr->funcs.passive_arg = passive_arg;
    attr->funcs.active_cb = active_cb;
    attr->funcs.active_arg = active_arg;
    attr->funcs.data_destroy_cb = destroy_cb;
    attr->funcs.data_destroy_arg = destroy_arg;

    return GLOBUS_SUCCESS;

  err:

    return res;
}
/********************************************************************
 *  external functions
 *  ------------------
 *
 *******************************************************************/
globus_result_t
globus_gridftp_server_control_event_send_restart(
    globus_gridftp_server_control_op_t      op,
    globus_range_list_t                     restart)
{
    GlobusGridFTPServerName(globus_gridftp_server_control_event_send_restart);

    if(op == NULL)
    {
        return GlobusGridFTPServerErrorParameter("op");
    }
    if(restart == NULL)
    {
        return GlobusGridFTPServerErrorParameter("restart");
    }


    globus_mutex_lock(&op->server_handle->mutex);
    {
        if(op->event.restart_running)
        {
            globus_l_gsc_send_restart(op, restart);
        }
    }
    globus_mutex_unlock(&op->server_handle->mutex);

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_attr_add_mode(
    globus_gridftp_server_control_attr_t    in_attr,
    char                                    mode)
{
    char                                    ch;
    char *                                  tmp_str;
    globus_i_gsc_attr_t *                   attr;
    globus_result_t                         res;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_add_mode);

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

    ch = toupper(mode);
    tmp_str = globus_common_create_string("%s%c", attr->modes, ch);
    globus_free(attr->modes);
    attr->modes = tmp_str;

    GlobusGridFTPServerDebugExit();
    return GLOBUS_SUCCESS;

  err:

    GlobusGridFTPServerDebugExitWithError();

    return res;
}
globus_result_t
globus_gridftp_server_control_attr_set_security(
    globus_gridftp_server_control_attr_t    in_attr,
    globus_gridftp_server_control_security_type_t sec)
{
    globus_i_gsc_attr_t *                   attr;
    globus_result_t                         res;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_set_security);

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

    attr->security = sec;

    GlobusGridFTPServerDebugExit();
    return GLOBUS_SUCCESS;

  err:

    GlobusGridFTPServerDebugExitWithError();
    return res;
}
globus_result_t
globus_gridftp_server_control_set_cwd(
    globus_gridftp_server_control_t         server,
    const char *                            cwd_string)
{
    GlobusGridFTPServerName(globus_gridftp_server_control_get_cwd);

    if(server == NULL)
    {
        return GlobusGridFTPServerErrorParameter("server");
    }

    globus_mutex_lock(&server->mutex);
    {
        if(cwd_string)
        {
            if(server->cwd)
            {
                globus_free(server->cwd);
            }
            server->cwd = strdup(cwd_string);
        }
        else if(server->cwd)
        {
            if(server->default_cwd)
            {
                globus_free(server->default_cwd);
            }
            server->default_cwd = strdup(server->cwd);
        }
    }
    globus_mutex_unlock(&server->mutex);

    return GLOBUS_SUCCESS;
}
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_gridftp_server_control_attr_copy(
    globus_gridftp_server_control_attr_t *  dst,
    globus_gridftp_server_control_attr_t    src)
{
    globus_result_t                         res;
    globus_i_gsc_attr_t *                   attr;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_copy);

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

    attr = (globus_i_gsc_attr_t *) globus_malloc(
                sizeof(globus_i_gsc_attr_t));
    if(attr == NULL)
    {
        res = GlobusGridFTPServerControlErrorSytem();
        goto err;
    }
    attr->version_ctl = src->version_ctl;
    attr->funcs.resource_cb = src->funcs.resource_cb;
    globus_hashtable_copy(
	    &attr->funcs.send_cb_table, &src->funcs.send_cb_table, NULL);
    globus_hashtable_copy(
        &attr->funcs.recv_cb_table, &src->funcs.recv_cb_table, NULL);
    attr->modes = globus_libc_strdup(src->modes);
    attr->types = globus_libc_strdup(src->types);

    *dst = attr;

    return GLOBUS_SUCCESS;

  err:

    GlobusGridFTPServerDebugExitWithError();

    return res;
}
/*************************************************************************
 *                      get functions
 *                      -------------
 ************************************************************************/
globus_bool_t
globus_gridftp_server_control_authenticated(
    globus_gridftp_server_control_t         server)
{
    globus_bool_t                           rc = GLOBUS_TRUE;
    globus_i_gsc_server_handle_t *          i_server;
    GlobusGridFTPServerName(globus_gridftp_server_control_authenticated);

    i_server = (globus_i_gsc_server_handle_t *) server;

    if(server == NULL)
    {
        return GLOBUS_FALSE;
    }

    return rc;
}
globus_result_t
globus_gridftp_server_control_get_data_auth(
    globus_gridftp_server_control_op_t      op,
    char **                                 subject,
    char *                                  dcau,
    char *                                  prot,
    gss_cred_id_t *                         del_cred)
{
    GlobusGridFTPServerName(globus_gridftp_server_control_get_data_auth);

    if(op == NULL)
    {
        return GlobusGridFTPServerErrorParameter("op");
    }

    globus_mutex_lock(&op->server_handle->mutex);
    {
        if(subject != NULL)
        {
            if(op->server_handle->dcau_subject != NULL)
            {
                *subject = globus_libc_strdup(op->server_handle->dcau_subject);
            }
            else
            {
                *subject = NULL;
            }
        }
        if(dcau != NULL)
        {
            *dcau = op->server_handle->dcau;
        }
        if(prot != NULL)
        {
            *prot = op->server_handle->prot;
        }
        if(del_cred != NULL)
        {
            *del_cred = op->server_handle->del_cred;
        }        
    }
    globus_mutex_unlock(&op->server_handle->mutex);

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_attr_set_banner(
    globus_gridftp_server_control_attr_t    in_attr,
    char *                                  banner)
{
    globus_i_gsc_attr_t *                   attr;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_set_list);

    if(in_attr == NULL)
    {
        return GlobusGridFTPServerErrorParameter("server_attr");
    }
    attr = (globus_i_gsc_attr_t *) in_attr;

    attr->pre_auth_banner = strdup(banner);

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_attr_set_resource(
    globus_gridftp_server_control_attr_t    in_attr,
    globus_gridftp_server_control_resource_cb_t resource_query_cb,
    void *                                  resource_arg)
{
    globus_i_gsc_attr_t *                   attr;
    globus_result_t                         res;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_resource_query);

    GlobusGridFTPServerDebugEnter();

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

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

    attr->funcs.resource_cb = resource_query_cb;
    attr->funcs.resource_arg = resource_arg;

    GlobusGridFTPServerDebugExit();

    return GLOBUS_SUCCESS;

  err:

    GlobusGridFTPServerDebugExitWithError();

    return res;
}
globus_result_t
globus_gridftp_server_control_event_send_perf(
    globus_gridftp_server_control_op_t      op,
    int                                     stripe_ndx,
    globus_off_t                            nbytes)
{
    GlobusGridFTPServerName(globus_gridftp_server_control_event_send_perf);

    if(op == NULL)
    {
        return GlobusGridFTPServerErrorParameter("op");
    }
    if(stripe_ndx < 0)
    {
        return GlobusGridFTPServerErrorParameter("stripe_ndx");
    }
    if(nbytes < 0)
    {
        return GlobusGridFTPServerErrorParameter("nbytes");
    }

    globus_mutex_lock(&op->server_handle->mutex);
    {
        if(op->event.stripe_total == NULL)
        {
            globus_mutex_unlock(&op->server_handle->mutex);
            return GlobusGridFTPServerErrorParameter("op");
        }
        op->event.stripe_total[stripe_ndx] += nbytes;
        if(op->event.perf_running)
        {
            globus_l_gsc_send_perf(
                op, 
                stripe_ndx, 
                op->event.stripe_count, 
                op->event.stripe_total[stripe_ndx]);
        }
    }
    globus_mutex_unlock(&op->server_handle->mutex);

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_get_cwd(
    globus_gridftp_server_control_t         server,
    char **                                 cwd_string)
{
    GlobusGridFTPServerName(globus_gridftp_server_control_get_cwd);

    if(server == NULL)
    {
        return GlobusGridFTPServerErrorParameter("server");
    }

    globus_mutex_lock(&server->mutex);
    {
        *cwd_string = globus_libc_strdup(server->cwd);
    }
    globus_mutex_unlock(&server->mutex);

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_get_list_type(
    globus_gridftp_server_control_op_t      op,
    int *                                   out_type)
{
    GlobusGridFTPServerName(globus_gridftp_server_control_get_list_type);

    if(op == NULL)
    {
        return GlobusGridFTPServerErrorParameter("op");
    }

    globus_mutex_lock(&op->server_handle->mutex);
    {
        *out_type = op->type;
    }
    globus_mutex_unlock(&op->server_handle->mutex);

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_attr_set_list(
    globus_gridftp_server_control_attr_t    in_attr,
    globus_gridftp_server_control_list_cb_t list_cb,
    void *                                  user_arg)
{
    globus_i_gsc_attr_t *                   attr;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_set_list);

    if(in_attr == NULL)
    {
        return GlobusGridFTPServerErrorParameter("server_attr");
    }
    attr = (globus_i_gsc_attr_t *) in_attr;

    attr->funcs.list_cb = list_cb;
    attr->funcs.list_arg = user_arg;

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_attr_set_idle_time(
    globus_gridftp_server_control_attr_t    in_attr,
    int                                     idle_timeout,
    int                                     preauth_timeout)
{
    globus_i_gsc_attr_t *                   attr;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_set_list);

    if(in_attr == NULL)
    {
        return GlobusGridFTPServerErrorParameter("server_attr");
    }
    attr = (globus_i_gsc_attr_t *) in_attr;

    attr->idle_timeout = idle_timeout;
    attr->preauth_timeout = preauth_timeout;

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_get_allocated(
    globus_gridftp_server_control_op_t      op,
    globus_off_t *                          out_allo)
{
    GlobusGridFTPServerName(globus_gridftp_server_control_get_parallelism);

    if(op == NULL)
    {
        return GlobusGridFTPServerErrorParameter("op");
    }

    globus_mutex_lock(&op->server_handle->mutex);
    {
        *out_allo = op->server_handle->allocated_bytes;
    }
    globus_mutex_unlock(&op->server_handle->mutex);

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_get_buffer_size(
    globus_gridftp_server_control_op_t      op,
    globus_size_t *                         out_recv_bs,
    globus_size_t *                         out_send_bs)
{
    GlobusGridFTPServerName(globus_gridftp_server_control_get_buffer_size);

    if(op == NULL)
    {
        return GlobusGridFTPServerErrorParameter("op");
    }

    globus_mutex_lock(&op->server_handle->mutex);
    {
        *out_recv_bs = op->server_handle->opts.receive_buf;
        *out_send_bs = op->server_handle->opts.send_buf;
    }
    globus_mutex_unlock(&op->server_handle->mutex);

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_get_layout(
    globus_gridftp_server_control_op_t      op,
    globus_gsc_layout_t *                   layout_type,
    globus_size_t *                         block_size)
{
    GlobusGridFTPServerName(globus_gridftp_server_control_get_layout);

    if(op == NULL)
    {
        return GlobusGridFTPServerErrorParameter("op");
    }

    globus_mutex_lock(&op->server_handle->mutex);
    {
        *layout_type = op->server_handle->opts.layout;
        *block_size = op->server_handle->opts.block_size;
    }
    globus_mutex_unlock(&op->server_handle->mutex);

    return GLOBUS_SUCCESS;
}
globus_result_t
globus_gridftp_server_control_attr_destroy(
    globus_gridftp_server_control_attr_t    in_attr)
{
    globus_i_gsc_module_func_t *            mod_func;
    globus_list_t *                         list;
    globus_i_gsc_attr_t *                   attr;
    globus_result_t                         res;
    GlobusGridFTPServerName(globus_gridftp_server_control_attr_destroy);

    GlobusGridFTPServerDebugEnter();

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

    attr = in_attr;

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

    if(attr->pre_auth_banner != NULL)
    {
        globus_free(attr->pre_auth_banner);
    }
    if(attr->post_auth_banner != NULL)
    {
        globus_free(attr->post_auth_banner);
    }

    globus_hashtable_to_list(&attr->funcs.recv_cb_table, &list);
    while(!globus_list_empty(list))
    {
        mod_func = (globus_i_gsc_module_func_t *)
            globus_list_remove(&list, list);
        globus_free(mod_func->key);
        globus_free(mod_func);
    }

    globus_hashtable_to_list(&attr->funcs.send_cb_table, &list);
    while(!globus_list_empty(list))
    {
        mod_func = (globus_i_gsc_module_func_t *)
            globus_list_remove(&list, list);
        globus_free(mod_func->key);
        globus_free(mod_func);
    }

    globus_hashtable_destroy(&attr->funcs.send_cb_table);
    globus_hashtable_destroy(&attr->funcs.recv_cb_table);

    globus_free(attr->base_dir);
    globus_free(attr->modes);
    globus_free(attr->types);
    globus_free(attr);

    GlobusGridFTPServerDebugExit();

    return GLOBUS_SUCCESS;

  err:

    GlobusGridFTPServerDebugExitWithError();

    return res;
}
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;
}