/*****************************************************************************
 *                                                                           *
 *  Copyright (c) 1991                                                       *
 *  by DIGITAL Equipment Corporation, Maynard, Mass.                         *
 *                                                                           *
 *  This software is furnished under a license and may be used and  copied   *
 *  only  in  accordance  with  the  terms  of  such  license and with the   *
 *  inclusion of the above copyright notice.  This software or  any  other   *
 *  copies  thereof may not be provided or otherwise made available to any   *
 *  other person.  No title to and ownership of  the  software  is  hereby   *
 *  transferred.                                                             *
 *                                                                           *
 *  The information in this software is subject to change  without  notice   *
 *  and  should  not  be  construed  as  a commitment by DIGITAL Equipment   *
 *  Corporation.                                                             *
 *                                                                           *
 *  DIGITAL assumes no responsibility for the use or  reliability  of  its   *
 *  software on equipment which is not supplied by DIGITAL.                  *
 *                                                                           *
 *****************************************************************************/

/*
 * SIMPLE_SERVER - A simple example of a DECmessageQ server program
 *                                                               
 * This program provides an example of a simple DECmessageQ
 * server. It receives a message from a client and responds by
 * returning the message.
 *                                                               
 * SIMPLE_SERVER can be run interactively, or started            
 * automatically by the SIMPLE_CLIENT program (on VMS only).
 *                                                               
 * SIMPLE_SERVER has the following logic flow:                   
 *                                                               
 *                +---------------------------+                  
 *                |  Attach to message queue  |                  
 *                |    using PAMS_ATTACH_Q    |                  
 *                +---------------------------+                  
 *                              |                                
 *                +---------------------------+                  
 *                | Initialize Variables, etc.|                  
 *                +---------------------------+                  
 *            +---------------->|                                
 *            |   +---------------------------+                  
 *            |   |   Wait for a message to   |                  
 *            |   |     be received using     |                  
 *            |   |       PAMS_GET_MSGW       |                  
 *            |   +---------------------------+                  
 *            |                 |                                
 *            |   +---------------------------+                  
 *            |   |  Send "canned" response   |                  
 *            |   |  message to client using  |                  
 *            |   |       PAMS_PUT_MSG        |                  
 *            |   +---------------------------+                  
 *            |                 |                                
 *            +---------<-------+                                
 *                                                               
 *                                                               
 * To build SIMPLE_SERVER on DECmessageQ for VMS:                         
 *                                                               
 * Use the SIMPLE_BUILD command procedure, or compile and   
 * link manually by using the following commands:           
 *                                                               
 *  $ CC/include=dmq$user/list/obj SIMPLE_SERVER
 *  $ LINK SIMPLE_SERVER,DMQ$LIB:DMQ/OPT                     
 *                                                               
 * A RUN command is used by SIMPLE_CLIENT to start SIMPLE_SERVER as a 
 * subprocess.                                                 
 *                                                               
 * To build SIMPLE_SERVER on non-DECmessageQ for VMS systems:    
 *                                                               
 * Compile with the "p_xxxx.h" include files, and link with 
 * DECmessageQ according to the documentation.                   
 *                                                               
 */

/* standard "C" and system definition files. 
 */
#include <stddef.h>
#include <types.h>
#include <stdio.h>                         /* standard I/O definitions        */
#include <stdlib.h>                        /* standard library definitions    */
#include <string.h>

#ifdef VMS
#include <ssdef.h>                           /* VMS system service return codes */
#include <stsdef.h>                          /* VMS system service status codes */
#endif

#define _NO_PROTO 1

#include "p_entry.h"                       /* PAMS function declarations      */
#include "p_proces.h"                      /* Known Queue number definitions  */
#include "p_group.h"                       /* Known Group ID definitions      */
#include "p_typecl.h"                      /* Generic Type/Class definitions  */
#include "p_return.h"                      /* PAMS return status definitions  */
#include "p_symbol.h"                      /* Generic PSEL/PSYM definitions   */

#ifndef VMS
#include "p_aretur.h"                      /* Remaining PAMS status defs      */
#endif

#define BUF_SIZE 512                       /* Buffer size for local buffers   */

/* Define data type for DECmessageQ target/source addresses.
 */
typedef union
   {
   long int      all;
   struct
      {
      short int  queue;
      short int  group;
      } au;
   } Q_address;

/* Declare local variables, pointers, and arrays
*/
char        start_server;                  /* Input to server question        */
long int    status;                        /* Completion status code          */

long int    attach_mode;                   /* Attach mode for PAMS_ATTACH_Q   */
long int    queue_type;                    /* Queue type for PAMS_ATTACH_Q    */
char        queue_name[32];                /* Queue name for PAMS_ATTACH_Q    */
long int    queue_name_length;             /* Length of queue name            */
long int    search_list[3] =               /* List of tables to search        */
                    { PSEL_TBL_PROC,
                      PSEL_TBL_GRP,
                      PSEL_TBL_DNS_LOW };
long int    search_list_len = 3;           /* Elements in search list         */

Q_address   queue_number;                  /* Actual queue number             */
struct PSB  psb;                           /* DECmessageQ status block        */

/* Define outbound ("put") message variables and arrays
*/
Q_address   target;                        /* Target queue address            */
char        put_buffer[BUF_SIZE+1];        /* Message buf. +1 null byte       */
short int   put_priority;                  /* Message priority                */
short int   put_class;                     /* Message class code              */
short int   put_type;                      /* Message type code               */
char        put_delivery;                  /* Delivery mode                   */
long int    put_resp_que;                  /* Response queue                  */
short int   put_size;                      /* Message size                    */
long int    put_timeout;                   /* Time to wait for delivery       */
char        put_uma;                       /* Undeliverable msg action        */

/* Define inbound ("get") message variables and arrays
*/
Q_address   source;                        /* Source queue address            */
char        get_buffer[BUF_SIZE+1];        /* Message buf. +1 null byte       */
short int   get_priority;                  /* Message priority                */
short int   get_class;                     /* Message class code              */
short int   get_type;                      /* Message type code               */
long int    get_select;                    /* Message selection mask          */
short int   get_size;                      /* Message size                    */
long int    get_timeout;                   /* Time to wait for message        */


#ifdef vms
static
#endif
main ()
{
    short        buflen = BUF_SIZE;

    printf ("\n\nSIMPLE_SERVER - Example starting\n");

    /* Setup parameters being passed to PAMS_ATTACH_Q
     */
    sprintf(queue_name, "%d", PAMS_QUEUE_1);/* Use a static name              */
    queue_name_length = strlen(queue_name);

    queue_type   = PSYM_ATTACH_PQ;
    attach_mode  = PSYM_ATTACH_BY_NUMBER;

    /* Call PAMS_ATTACH_Q to attach our program to a permanent queue
     * and assign our queue number.
     */
    status = pams_attach_q (&attach_mode, &queue_number, &queue_type,
                            queue_name, &queue_name_length, 0, 0, 0, 0, 0);

    if (status != PAMS__SUCCESS)
    {
        printf("SIMPLE_SERVER: Error returned by PAMS_ATTACH_Q %d\n",status);
        exit(status);
    }

    printf("\n\nSIMPLE_SERVER: Attached to queue %d.%d\n",
           queue_number.au.group, queue_number.au.queue);

    /* Initialize the variables that we will be using for messaging.
     */
    get_priority = 0;                      /* Receive all priority messages   */
    get_timeout  = 0;                      /* Wait "forever" for a message    */
    get_select   = 0;                      /* No special selection mask       */

    put_class    = 1;                      /* Send class 1 message            */
    put_priority = 0;                      /* Send at standard priority       */
    put_resp_que = 0;                      /* Response queue - default        */
    put_type     = -123;                   /* Message type is program defined */
    put_timeout  = 0;                      /* Accept standard put timeout     */
    put_delivery = PDEL_MODE_NN_MEM;       /* No notify, memory queuing       */
    put_uma      = PDEL_UMA_DISC;          /* Discard if undeliverable        */
                        
    while (1)
    {
        /* Wait for a message to be sent by a client program.
         * If timeout status returned received, report it and continue. 
         * If any other error, report it and exit. Otherwise, display
         * the message.
         */
        if ((status = pams_get_msgw (get_buffer, &get_priority, &source.all,
                                     &get_class, &get_type, &buflen, &get_size, 
                                     &get_timeout, &get_select, &psb,
                                     0, 0, 0, 0, 0)) == PAMS__TIMEOUT)
            printf ("SIMPLE_SERVER: PAMS_GET_MSGW Timeout.  Continuing\n");

        else if (status != PAMS__SUCCESS)
        {
            printf ("SIMPLE_SERVER: Error returned by PAMS_GET_MSGW code = %d\n",
                    status);
            exit (status);
        }

        printf ("\nSIMPLE_SERVER: Received from %d.%d class=%d, type=%d\n",
                source.au.group, source.au.queue, 
                get_class, get_type);
        printf ("Msg = '%s'\n", get_buffer);

        /* Return "canned" response message to the client program.
         * Message returned contains client queue number and the first
         * 50 characters of the message received.
         */


        (void)sprintf (put_buffer, 
             "Message from %d.%d is \"%.50s\" \n", 
              source.au.group, source.au.queue,
              get_buffer);

        put_size = strlen(put_buffer);

        /* Set target queue to that of the queue that sent the
         * message, then send the response message.
         */
        target.all = source.all;
        if ((status = pams_put_msg(put_buffer, &put_priority, &target.all,
                                   &put_class, &put_type, &put_delivery,
                                   &put_size,  &put_timeout, &psb, &put_uma,
                                   &put_resp_que, 0, 0, 0)) != PAMS__SUCCESS)

        {
            printf ("SIMPLE_SERVER: Error returned by PAMS_PUT_MSG code = %d\n",
                     status);
            exit (status);
        }    

        printf ("\nSIMPLE_SERVER: Sent Msg to %d.%d class = %d, type = %d\n",
                target.au.group, target.au.queue, 
                put_class, put_type);
        printf ("Msg = '%s'\n", put_buffer);
    }
} /* End of SIMPLE_SERVER.C */







