/* @(#)86    1.20  src/examples/type_mgr/server.c, examples.src, os2dce21.dss, 960602a.1 1/12/96 14:30:47 */
/*
 * COMPONENT_NAME:  examples.src
 *
 * FUNCTIONS:
 *
 * ORIGINS: 27
 *
 * (C) COPYRIGHT International Business Machines Corp. 1992, 1994
 * All Rights Reserved
 * Licensed Materials - Property of IBM
 *
 * US Government Users Restricted Rights - Use, duplication or
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *
 */

/*********************************************************************
 *  File      :  server.c                                            *
 *********************************************************************
 *                                                                   *
 *  Functions :  main()                                              *
 *                                                                   *
 *  Comments  :  RPC server application program.  This file serves   *
 *               as a skeleton that gives the server program a       *
 *               consistent look and feel.                           *
 *                                                                   *
 *********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <dce/pthread.h>
#include <dce/rpc.h>
#include <dce/dce_error.h>
#include "cust_if.h"
#include <util.h>
#include "type_mgr.h"
#include "server.h"

/*
 *  Global type table.  Array of entries, each containing the type name
 *  and string uuid.
 */

type_table_t type_table[NUM_TYPE_MGRS];
/*
 *  Status Messages.
 */

char *tm_msg[] =
{
"Success",
"Failure",
"No match",
"No more entries",
"Object already exists",
"Coding error",
"Object database created",
"Object database restarted",
"Object database initialization in progress",
"Object database unititialized"
};

extern unsigned32 server_shutdown(void);


/*********************************************************************
 *   Function    :  main()                                           *
 *********************************************************************
 *                                                                   *
 *   Description :  Makes calls to subroutines to carry out the      *
 *                  tasks of initialization, processing, and         *
 *                  shutdown.                                        *
 *                  DCE exception handling is implemented to         *
 *                  catch any exceptions that the RPC runtime        *
 *                  or pthreads raise.  The exception handling       *
 *                  routine print_exception() examines the exception *
 *                  structure and prints a text string indicating    *
 *                  what the exception was.                          *
 *                  The lets_exit variable is used to keep the       *
 *                  program from plowing ahead after a fatal error   *
 *                  has been encountered.  We don't just exit        *
 *                  immediately since the program, whether it        *
 *                  succeeds or fails must report a status string.   *
 *                  This is done in one convenient spot at the end.  *
 *                  The pthread_signal_to_cancel_np() call           *
 *                  registers the specified signals with the         *
 *                  threads library.  It sets up signal handlers     *
 *                  that will cancel the specified thread when       *
 *                  that signal is caught.                           *
 *                                                                   *
 *   Returns     :  (0) success, (1) failure                         *
 *                                                                   *
 *********************************************************************/
int main( unsigned32 argc,
      char       *argv[] )
{
    unsigned32           status;
    sigset_t             signals_to_catch;
    pthread_t            this_thread;

    /*
     *  Parse the command line arguments.  The main program does not
     *  deal with them.  See server_args.c for how cmd line args are used.
     */

    if (( status = server_args( argc, argv )) != SUCCESS )
    {
        goto exit;
    }

    /*
     *  Setup the server interface(s) that will be provided to the
     *  administration application.
     */

    if (( status = server_setup_admin()) != SUCCESS )
    {
    goto exit;
    }

    /*
     *  Setup the server interface(s) that will be provided to all
     *  client applications (NOTE: this does NOT include the administration
     *  application).
     *
     *  Both server_setup_admin and this routine (server_setup) call
     *  rpc_server_use_all_protseqs which acquires a socket (port, endpoint).
     *    Since this routine calls it last, the port that will be returned
     *  in the binding handles from subsequent calls to
     *  rpc_server_inq_bindings will be the one acquired here.  This will
     *  be the port all rpc calls to the object manager routines will
     *  arrive on (the endpoint registered with the object uuids in the
     *  endpoint map.  In essence, this leaves the port acquired by
     *  server_setup_admin reserved for admin calls.  We have not investigated
     *  the ramifications of this.
     */

    if (( status = server_setup()) != SUCCESS )
    {
    goto exit;
    }

    /*
     *  Set up signals we want threads to catch.  If any of these
     *  signals is caught, this thread (the main thread) will have
     *  an exception raised, and the appropriate action will take
     *  place.  This protects us in many cases from aborting without
     *  cleaning up the endpoint map, name service, etc...
     */

    sigemptyset(&signals_to_catch);
    sigaddset(&signals_to_catch, SIGINT);
#ifndef IBMOS2
    sigaddset(&signals_to_catch, SIGQUIT);
#endif
    sigaddset(&signals_to_catch, SIGTERM);
    this_thread = pthread_self();

    if ((status = pthread_signal_to_cancel_np( &signals_to_catch,
                          &this_thread )) != 0)
    {
    /*
     *  Any error codes for pthread_signal_to_cancel_np() are
     *  returned in the global errno variable.
     */

    perror("Error:  pthread_signal_to_cancel_np()\n");

    }

    TRY
    {
    /*
     * At this point, the server is ready to listen for requests
     * from both the client and management applications.
     */

    printf("Server is listening...\n");
    rpc_server_listen( 5,
              &status );

    CHECK_STATUS( "rpc_server_listen()\n",
             status,
             CONTINUE );

    if (!status)
    {
        TRACE("Server has stopped listening\n");
    }
    }
    CATCH_ALL
    {
    /*
     *  Currently, just print the exception, and fall through
     *  to the finally clause.
     */

    print_exception(THIS_CATCH);

    }
    FINALLY
    {
    /*
     *  Note that any code in the FINALLY clause of this exception
     *  handling mechanism will be run under all circumstances,
     *  whether an exception is raised or not.
     */

    /*  currently nothing to do */

    }
    ENDTRY

 exit:

    /*
     *  Upon exiting, we will always run the server_shutdown()
     *  routine.  This ensures that things get cleaned up properly.
     */

    if (( status = server_shutdown()) != SUCCESS )
    {
        /* currently nothing special to do */
    }

    return( status );

} /* end main() */

/* EOF server.c */

