/*
 * nasd_edrfs_dce.c
 *
 * DCE-RPC dispatch for NASD EDRFS server.
 *
 * Authors: Jim Zelenka, Nat Lanza, Mathew Monroe
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1997,1998,1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#include <nasd/nasd_options.h>

#if NASD_RPC_PACKAGE == NASD_RPC_PACKAGE_DCE

#undef  NASD_PTHREAD_EXC
#define NASD_PTHREAD_EXC 1
#include <nasd/nasd_types.h>
#include <nasd/nasd_edrfs_types.h>
#include <nasd/nasd_freelist.h>
#include <nasd/nasd_itypes.h>
#include <nasd/nasd_mem.h>
#include <nasd/nasd_common.h>
#include <nasd/nasd_edrfs_internal.h>
#include <nasd/nasd_edrfs_server.h>
#include <nasd/nasd_edrfs_server_internal.h>
#include <nasd/nasd_control.h>
#include <nasd/nasd_timer.h>
#include <nasd/nasd_marshall.h>
#include <nasd/nasd_edrfs_rpc.h>
#include <nasd/nasd_timeout.h>

#include <nasd/nasd_pipe.h>
#include <nasd/nasd_pipe_dce.h>

#include <sys/errno.h>

#ifdef KERNEL
#include <dce/ker/pthread_exc.h>
#endif /* KERNEL */
#include <rpc/rpc.h>
#include <dce/stubbase.h>

int nasd_edrfs_dce_protseq_installed = 0;

nasd_edrfs_lookup_res_t nasd_edrfs_dce_lookup_failmem;

/* Don't use __FILE__ here to avoid getting kernel-mangled names */
#define NASD_EDRFS_RPC_RETURN(_statval_) { \
  *op_status = _statval_; \
  return; \
}
#define DOBEGIN(_opname_) NASD_EDRFS_RPC_DOBEGIN(_opname_,"nasd_edrfs_dce.c")
#define DORETURN(_opname_) NASD_EDRFS_RPC_DORETURN(_opname_,"nasd_edrfs_dce.c")

/*
 * RPC handlers begin here
 */

void nasd_sedrfs_null_fm(
  handle_t         client_handle, 
  nasd_res_otw_t   out_res_otw,
  error_status_t  *op_status)
{
  nasd_res_t res;
  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(null);
  res.nasd_status = NASD_SUCCESS;
  nasd_res_t_marshall(&res, out_res_otw);
  DORETURN(null);
}


void
nasd_sedrfs_mount_fm(
  handle_t                      client_handle,
  nasd_edrfs_mount_args_otw_t   in_args_otw,
  nasd_edrfs_mount_res_otw_t    out_res_otw,
  error_status_t               *op_status)
{
  nasd_edrfs_mount_args_t args;
  nasd_edrfs_mount_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(mount);

  nasd_edrfs_mount_args_t_unmarshall(in_args_otw, &args);

  args.in_dirpath[NASD_EDRFS_MAX_NAME_LEN-1] = '\0';

  TRY {
    nasd_edrfs_real_mount(args.in_credential,
                          (char *)args.in_dirpath,
                          NASD_EDRFS_DRIVE_LIST_LEN,
                          res.out_drivelist,
                          &res.out_listlen,
                          &res.out_cookie,
                          &res.out_identifier,
                          &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing mount\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_mount_res_t_marshall(&res, out_res_otw);

  DORETURN(mount);
}


void
nasd_sedrfs_fsstat_fm(
  handle_t                       client_handle,
  nasd_edrfs_fsstat_args_otw_t   in_args_otw,
  nasd_edrfs_fsstat_res_otw_t    out_res_otw,
  error_status_t                *op_status)
{
  nasd_edrfs_fsstat_args_t args;
  nasd_edrfs_fsstat_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(fsstat);

  nasd_edrfs_fsstat_args_t_unmarshall(in_args_otw, &args);

  TRY {
    nasd_edrfs_real_fsstat(args.in_cookie,
                           args.in_identifier,
                           args.in_credential,
                           &res.out_stat,
                           &res.out_attribute,
                           &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing fsstat\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_fsstat_res_t_marshall(&res, out_res_otw);

  DORETURN(fsstat);
}


void
nasd_sedrfs_fsinfo_fm(
  handle_t                       client_handle,
  nasd_edrfs_fsinfo_args_otw_t   in_args_otw,
  nasd_edrfs_fsinfo_res_otw_t    out_res_otw,
  error_status_t                *op_status)
{
  nasd_edrfs_fsinfo_args_t args;
  nasd_edrfs_fsinfo_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(fsinfo);

  nasd_edrfs_fsinfo_args_t_unmarshall(in_args_otw, &args);

  TRY {
    nasd_edrfs_real_fsinfo(args.in_cookie,
                           args.in_identifier,
                           args.in_credential,
                           &res.out_info,
                           &res.out_attribute,
                           &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing fsinfo\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_fsinfo_res_t_marshall(&res, out_res_otw);

  DORETURN(fsinfo);
}


void
nasd_sedrfs_lookup_fm(
  handle_t                       client_handle, 
  nasd_edrfs_lookup_args_otw_t   in_args_otw,
  nasd_edrfs_lookup_res_otw_t    out_res_otw,
  error_status_t                *op_status)
{
  nasd_status_t rc;
  nasd_edrfs_lookupstuff_t *lus;
  nasd_edrfs_rpc_basic_t res;
  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(lookup);

  lus = nasd_edrfs_get_lookupstuff();
  if (lus == NULL) {
    /* marshall a failure */
    nasd_edrfs_lookup_res_t_marshall(&nasd_edrfs_dce_lookup_failmem, out_res_otw);
    goto really_done_lookup;
  }

  nasd_edrfs_lookup_args_t_unmarshall(in_args_otw, &lus->in_args);

  lus->in_args.in_dirpath[NASD_EDRFS_MAX_NAME_LEN-1] = '\0';

  nasd_edrfs_real_lookup(lus->in_args.in_cookie,
                         lus->in_args.in_identifier,
                         lus->in_args.in_credential,
                         (char *)lus->in_args.in_dirpath,
                         &lus->out_res.out_cookie,
                         &lus->out_res.out_identifier,
                         &lus->out_res.out_attribute,
                         &lus->out_res.post_attribute,
                         &rc);
  lus->out_res.nasd_status = rc;

  nasd_edrfs_lookup_res_t_marshall(&lus->out_res, out_res_otw);

really_done_lookup:
#if (DEBUG_LOOKUP_DETAIL > 0) || (DEBUG_RPC_ERR_DETAIL > 0)
  if (lus == NULL) {
    nasd_printf("lookup complete lus NULL\n");
  }
  else if (rc) {
    nasd_printf("lookup returning nasd status 0x%x (%s) for in_dirpath=\"%s\"\n", rc, nasd_error_string(rc), (char *)lus->in_args.in_dirpath);
  }
#if DEBUG_LOOKUP_DETAIL > 0
  else if (lus->out_res.out_attribute.valid != NASD_EDRFS_ATTRIBUTE_VALID) {
    nasd_printf("lookup Successful with invalid attribute for in_dirpath=\"%s\" nasdid 0x%"
           NASD_ID_FMT "\n",
      (char *)lus->in_args.in_dirpath,
      lus->out_res.out_identifier.nasd_identifier);
    if (lus->out_res.out_attribute.valid == NASD_EDRFS_ATTRIBUTE_INVALID) {
      nasd_printf("lus->out_res.out_attribute.valid = INVALID\n");
    }
    else {
      nasd_printf("lus->out_res.out_attribute.valid = 0x%x\n", ((int)lus->out_res.out_attribute.valid)&0xff);
    }
  }
  else {
    nasd_printf("lookup_otw Successful for in_dirpath=\"%s\" nasdid 0x%"
           NASD_ID_FMT "\n%s attributes: ",
           (char *)lus->in_args.in_dirpath,
           lus->out_res.out_identifier.nasd_identifier,
           (char *)lus->in_args.in_dirpath);
    nasd_dump_edrfs_attributes_otw((nasd_otw_base_t *)lus->out_res.out_attribute.attribute.fs_specifc);
    nasd_printf("\n");
#ifndef KERNEL
    fflush(stdout);
#endif /* !KERNEL */
  }
#endif /* DEBUG_LOOKUP_DETAIL > 0 */
#endif /* (DEBUG_LOOKUP_DETAIL > 0) || (DEBUG_RPC_ERR_DETAIL > 0) */

  if (lus) {
    nasd_edrfs_free_lookupstuff(lus);
  }

  res.nasd_status = rc;
  DORETURN(lookup);
}


void
nasd_sedrfs_readdir_fm(
  handle_t                        client_handle,
  nasd_edrfs_readdir_args_otw_t   in_args_otw,
  nasd_byte_pipe_t                byte_pipe,
  nasd_edrfs_readdir_res_otw_t    out_res_otw,
  error_status_t                 *op_status)
{
  nasd_edrfs_readdir_args_t args;
  nasd_edrfs_readdir_res_t res;
  nasd_edrfs_dirent_otw_t dirent_otw;
  nasd_procpipe_t procpipe;
  int i;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(readdir);

  nasd_edrfs_readdir_args_t_unmarshall(in_args_otw, &args);

  procpipe.state = &byte_pipe;
  procpipe.push = nasd_dceprocpipe_push;
  procpipe.pull = NULL;

  TRY {
    nasd_edrfs_real_readdir(args.in_cookie,
                            args.in_identifier,
                            args.in_credential,
                            args.in_marker,
                            args.in_markerv,
                            args.in_count,
                            &res.out_marker,
                            &res.out_markerv,
                            &res.out_count,
                            &res.out_eof,
                            &procpipe,
                            &res.post_attribute,
                            &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing readdir\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  if (res.nasd_status != NASD_RPC_TRAP) {
    procpipe.push(procpipe.state, dirent_otw, 0, NULL, NULL, NULL);
  }

really_done_readdir:
  nasd_edrfs_readdir_res_t_marshall(&res, out_res_otw);
  DORETURN(readdir);
}

void
nasd_sedrfs_access_fm(
  handle_t                       client_handle,
  nasd_edrfs_access_args_otw_t   in_args_otw,
  nasd_edrfs_access_res_otw_t    out_res_otw,
  error_status_t                *op_status)
{
  nasd_edrfs_access_args_t args;
  nasd_edrfs_access_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(access);

  nasd_edrfs_access_args_t_unmarshall(in_args_otw, &args);

  TRY {
    nasd_edrfs_real_access(args.in_cookie,
                           args.in_identifier,
                           args.in_credential,
                           args.in_access,
                           &res.out_access,
                           &res.post_attribute,
                           &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing access\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_access_res_t_marshall(&res, out_res_otw);

  DORETURN(access);
}

void
nasd_sedrfs_setattr_fm(
  handle_t                        client_handle,
  nasd_edrfs_setattr_args_otw_t   in_args_otw,
  nasd_edrfs_setattr_res_otw_t    out_res_otw,
  error_status_t                 *op_status)
{
  nasd_edrfs_setattr_args_t args;
  nasd_edrfs_setattr_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(setattr);

  nasd_edrfs_setattr_args_t_unmarshall(in_args_otw, &args);

  TRY {
    nasd_edrfs_real_setattr(args.in_cookie,
                            args.in_identifier,
                            args.in_credential,
                            args.in_attribute,
                            args.in_fieldmask,
                            args.in_guard,
                            &res.out_attribute,
                            &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing setattr\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_setattr_res_t_marshall(&res, out_res_otw);

  DORETURN(setattr);
}

void
nasd_sedrfs_create_fm(
  handle_t                       client_handle,
  nasd_edrfs_create_args_otw_t   in_args_otw,
  nasd_edrfs_create_res_otw_t    out_res_otw,
  error_status_t                *op_status)
{
  nasd_edrfs_create_args_t args;
  nasd_edrfs_create_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(create);

  nasd_edrfs_create_args_t_unmarshall(in_args_otw, &args);

  args.in_dirpath[NASD_EDRFS_MAX_NAME_LEN-1] = '\0';

  TRY {
    nasd_edrfs_real_create(args.in_cookie,
                           args.in_directory,
                           args.in_credential,
                           (char *)args.in_dirpath,
                           args.in_attribute,
                           args.in_fieldmask,
                           &res.out_cookie,
                           &res.out_identifier,
                           &res.out_attribute,
                           &res.post_attribute,
                           &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing create\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_create_res_t_marshall(&res, out_res_otw);

  DORETURN(create);
}

void
nasd_sedrfs_symlink_fm(
  handle_t                        client_handle,
  nasd_edrfs_symlink_args_otw_t   in_args_otw,
  nasd_edrfs_symlink_res_otw_t    out_res_otw,
  error_status_t                 *op_status)
{
  nasd_edrfs_symlink_args_t args;
  nasd_edrfs_symlink_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(symlink);

  nasd_edrfs_symlink_args_t_unmarshall(in_args_otw, &args);

  args.in_dirpath[NASD_EDRFS_MAX_NAME_LEN-1] = '\0';
  args.in_symlink[NASD_EDRFS_MAX_NAME_LEN-1] = '\0';

  TRY {
    nasd_edrfs_real_symlink(args.in_cookie,
                            args.in_directory,
                            args.in_credential,
                            (char *)args.in_dirpath,
                            (char *)args.in_symlink,
                            args.in_attribute,
                            &res.out_cookie,
                            &res.out_identifier,
                            &res.out_attribute,
                            &res.post_attribute,
                            &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing symlink\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_symlink_res_t_marshall(&res, out_res_otw);

  DORETURN(symlink);
}

void
nasd_sedrfs_remove_fm(
  handle_t                       client_handle,
  nasd_edrfs_remove_args_otw_t   in_args_otw,
  nasd_edrfs_remove_res_otw_t    out_res_otw,
  error_status_t                *op_status)
{
  nasd_edrfs_remove_args_t args;
  nasd_edrfs_remove_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(remove);

  nasd_edrfs_remove_args_t_unmarshall(in_args_otw, &args);

  args.in_dirpath[NASD_EDRFS_MAX_NAME_LEN-1] = '\0';

  TRY { 
    nasd_edrfs_real_remove(args.in_cookie,
                           args.in_directory,
                           args.in_credential,
                           (char *)args.in_dirpath,
                           &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing remove\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_remove_res_t_marshall(&res, out_res_otw);

  DORETURN(remove);
}

void
nasd_sedrfs_mkdir_fm(
  handle_t                      client_handle,
  nasd_edrfs_mkdir_args_otw_t   in_args_otw,
  nasd_edrfs_mkdir_res_otw_t    out_res_otw,
  error_status_t               *op_status)
{
  nasd_edrfs_mkdir_args_t args;
  nasd_edrfs_mkdir_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(mkdir);

  nasd_edrfs_mkdir_args_t_unmarshall(in_args_otw, &args);

  args.in_dirpath[NASD_EDRFS_MAX_NAME_LEN-1] = '\0';

  TRY {
    nasd_edrfs_real_mkdir(args.in_cookie,
                          args.in_directory, 
                          args.in_credential,
                          (char *)args.in_dirpath,
                          args.in_attribute,
                          args.in_fieldmask,
                          &res.out_cookie,
                          &res.out_identifier,
                          &res.out_attribute,
                          &res.post_attribute,
                          &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing mkdir\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_mkdir_res_t_marshall(&res, out_res_otw);

  DORETURN(mkdir);
}

void
nasd_sedrfs_rmdir_fm(
  handle_t                      client_handle,
  nasd_edrfs_rmdir_args_otw_t   in_args_otw,
  nasd_edrfs_rmdir_res_otw_t    out_res_otw,
  error_status_t               *op_status)
{
  nasd_edrfs_rmdir_args_t args;
  nasd_edrfs_rmdir_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(rmdir);

  nasd_edrfs_rmdir_args_t_unmarshall(in_args_otw, &args);

  args.in_dirpath[NASD_EDRFS_MAX_NAME_LEN-1] = '\0';

  TRY {
    nasd_edrfs_real_rmdir(args.in_cookie,
                          args.in_directory,
                          args.in_credential,
                          (char *)args.in_dirpath,
                          &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing rmdir\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_rmdir_res_t_marshall(&res, out_res_otw);

  DORETURN(rmdir);
}

void
nasd_sedrfs_newcookie_fm(
  handle_t                          client_handle,
  nasd_edrfs_newcookie_args_otw_t   in_args_otw,
  nasd_edrfs_newcookie_res_otw_t    out_res_otw,
  error_status_t                   *op_status)
{
  nasd_edrfs_newcookie_args_t args;
  nasd_edrfs_newcookie_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(newcookie);
  
  nasd_edrfs_newcookie_args_t_unmarshall(in_args_otw, &args);

  TRY {
    nasd_edrfs_real_newcookie(args.in_identifier,
                              args.in_credential,
                              &res.out_cookie,
                              &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing newcookie\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_newcookie_res_t_marshall(&res, out_res_otw);

  DORETURN(newcookie);
}

void
nasd_sedrfs_rename_fm(
  handle_t                       client_handle,
  nasd_edrfs_rename_args_otw_t   in_args_otw,
  nasd_edrfs_rename_res_otw_t    out_res_otw,
  error_status_t                *op_status)
{
  nasd_edrfs_rename_args_t args;
  nasd_edrfs_rename_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(rename);

  nasd_edrfs_rename_args_t_unmarshall(in_args_otw, &args);

  args.in_from_path[NASD_EDRFS_MAX_NAME_LEN-1] = '\0';
  args.in_to_path[NASD_EDRFS_MAX_NAME_LEN-1] = '\0';

  TRY {
    nasd_edrfs_real_rename(args.in_cookie,
                           args.in_from_directory,
                           args.in_credential,
                           (char *)args.in_from_path,
                           args.in_to_directory,
                           (char *)args.in_to_path,
                           &res.post_from_attribute,
                           &res.post_to_attribute,
                           &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing rename\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_rename_res_t_marshall(&res, out_res_otw);

  DORETURN(rename);
}

void
nasd_sedrfs_getstats_fm(
  handle_t                        client_handle,
  nasd_edrfs_getstats_res_otw_t   out_res_otw,
  error_status_t                 *op_status)
{
  nasd_edrfs_getstats_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(getstats);

  TRY {
    nasd_edrfs_real_getstats(&res.out_opstats,
                             &res.out_cachestats,
                             &res.out_opdepths,
                             &res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing getstats\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_edrfs_getstats_res_t_marshall(&res, out_res_otw);

  DORETURN(getstats);
}


void
nasd_sedrfs_resetstats_fm(
  handle_t         client_handle,
  nasd_res_otw_t   out_res_otw,
  error_status_t  *op_status)
{
  nasd_res_t res;

  NASD_EDRFS_RPC_OP_STATS_DECL

  DOBEGIN(resetstats);

  TRY {
    nasd_edrfs_real_resetstats(&res.nasd_status);
  }
  CATCH_ALL {
    res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("EDRFS: caught exception performing resetstats\n");
#endif /* NASD_EDRFS_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_res_t_marshall(&res, out_res_otw);

  DORETURN(resetstats);
}


/*
 * RPC mechanism begins here
 */

/*
 * !!! Do not hand-modify! Generate this stanza with "make mepv"
 */

static nasd_edrfs_server_v0_1_epv_t nasd_edrfs_server_epv = {
  nasd_sedrfs_null_fm
  ,nasd_sedrfs_mount_fm
  ,nasd_sedrfs_fsstat_fm
  ,nasd_sedrfs_fsinfo_fm
  ,nasd_sedrfs_lookup_fm
  ,nasd_sedrfs_readdir_fm
  ,nasd_sedrfs_access_fm
  ,nasd_sedrfs_setattr_fm
  ,nasd_sedrfs_create_fm
  ,nasd_sedrfs_symlink_fm
  ,nasd_sedrfs_remove_fm
  ,nasd_sedrfs_mkdir_fm
  ,nasd_sedrfs_rmdir_fm
  ,nasd_sedrfs_newcookie_fm
  ,nasd_sedrfs_rename_fm
  ,nasd_sedrfs_getstats_fm
  ,nasd_sedrfs_resetstats_fm
};

nasd_status_t
nasd_edrfs_rpc_specific_init()
{
  nasd_status_t rc;

  bzero((char *)&nasd_edrfs_dce_lookup_failmem, sizeof(nasd_edrfs_dce_lookup_failmem));
  nasd_edrfs_dce_lookup_failmem.nasd_status = NASD_NO_MEM;

  rc = nasd_dcepipe_init(nasd_edrfs_shutdown);
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_dcepipe_init()\n",
      rc, nasd_error_string(rc));
    nasd_edrfs_really_shutdown();
    return(rc);
  }

  return(NASD_SUCCESS);
}

nasd_status_t
nasd_edrfs_rpc_specific_startup()
{
  rpc_binding_vector_p_t binding_vector;
  rpc_if_handle_t nasd_edrfs_ifspec;
  rpc_if_rep_p_t nasd_edrfs_ifrep;
  dce_error_string_t err_str;
  error_status_t status;
  int ps;
  nasd_status_t rc;

  nasd_edrfs_ifrep = (rpc_if_rep_p_t)nasd_edrfs_server_v0_1_s_ifspec;
  nasd_edrfs_ifrep->manager_epv = (rpc_mgr_epv_t)&nasd_edrfs_server_epv;
  nasd_edrfs_ifspec = nasd_edrfs_server_v0_1_s_ifspec;

  if (nasd_edrfs_dce_protseq_installed == 0) {
    rpc_server_use_protseq_if((unsigned_char_t *)"ncadg_ip_udp",
      rpc_c_protseq_max_reqs_default, nasd_edrfs_ifspec, &status);
    if (status != rpc_s_ok) {
      dce_error_inq_text(status, err_str, &ps);
      if (ps)
        strcpy(err_str, "unknown");
      nasd_printf("EDRFS ERROR: cannot register protocol sequence 0x%x (%s)\n",
        (unsigned)status, err_str);
      return(NASD_FAIL);
    }
    nasd_edrfs_dce_protseq_installed = 1;
  }

  rpc_server_register_if(nasd_edrfs_ifspec, NULL, NULL, &status);
  if (status != rpc_s_ok) {
    dce_error_inq_text(status, err_str, &ps);
    if (ps)
      strcpy(err_str, "unknown");
    nasd_printf("EDRFS ERROR: cannot register interface 0x%x (%s)\n",
      (unsigned)status, err_str);
    return(NASD_FAIL);
  }

#if 0
  rpc_server_inq_bindings(&binding_vector, &status);
  if (status != rpc_s_ok) {
    dce_error_inq_text(status, err_str, &ps);
    if (ps)
      strcpy(err_str, "unknown");
    nasd_printf("EDRFS ERROR: cannot retrieve binding information 0x%x (%s)\n",
      (unsigned)status, err_str);
    return(NASD_FAIL);
  }
#endif

  return(NASD_SUCCESS);
}

void
nasd_edrfs_rpc_specific_stop()
{
  rpc_if_handle_t nasd_edrfs_ifspec;
  dce_error_string_t err_str;
  error_status_t status;
  int ps;

  nasd_edrfs_active = 0;

  nasd_edrfs_ifspec = nasd_edrfs_server_v0_1_s_ifspec;

#if 0
  /*
   * This just doesn't work. Hurray DCE.
   */
  rpc_mgmt_stop_server_listening(NULL, &status);
  if (status) {
    dce_error_inq_text(status, err_str, &ps);
    if (ps)
      strcpy(err_str, "unknown");
    nasd_printf("EDRFS: cannot stop server listener status %d (%s)\n",
      status, err_str);
  }
#endif /* 0 */

  rpc_server_unregister_if(nasd_edrfs_ifspec, NULL, &status);
  if (status) {
    dce_error_inq_text(status, err_str, &ps);
    nasd_printf("EDRFS: doubleplusungood, cannot unregister server_if status %d (%s)\n",
      status, err_str);
    NASD_PANIC();
  }
}

nasd_status_t
nasd_edrfs_rpc_specific_listen(
  int          service_threads,
  nasd_uint16  ipport)
{
  char err_str[dce_c_error_string_len];
  error_status_t status;
  int dce_ps;

  rpc_server_listen(service_threads, &status);

  if (status) {
#ifdef KERNEL
    if (status == rpc_s_already_listening)
      return(NASD_SUCCESS);
#endif /* KERNEL */

    dce_error_inq_text(status, err_str, &dce_ps);

    if (dce_ps) {
      strcpy(err_str, "unknown");
    }

    nasd_printf("EDRFS ERROR: DCE listener aborted! status=0x%x (%s)\n",
      status, err_str);

    return(NASD_FAIL);
  }

  return(NASD_SUCCESS);
}

nasd_status_t
nasd_edrfs_rpc_specific_set_stacksize(
  int  stacksize)
{
#if defined(DEC_OSF) && defined(KERNEL)
  return(NASD_OP_NOT_SUPPORTED);
#else /* defined(DEC_OSF) && defined(KERNEL) */
  error_status_t status;

  /* XXX better error handling */

  rpc_mgmt_set_server_stack_size(stacksize, &status);
  if (status)
    return(NASD_FAIL);

  return(NASD_SUCCESS);
#endif /* defined(DEC_OSF) && defined(KERNEL) */
}

#endif /* NASD_RPC_PACKAGE == NASD_RPC_PACKAGE_DCE */

/* Local Variables:  */
/* indent-tabs-mode: nil */
/* tab-width: 2 */
/* End: */
