/*   HAVE.C     Server for Peter/Pete's IPC system.        bjw  june 88 */

/*
//              This server provides the function of multiplication:
//              You pass two numbers, the result is their product.  This is
//              meant to be a pseudo-test suite for the Manx IPC product.
//              Send us a BREAK C to cause us to exit.
//
//              bjw             25-june-88      Initial coding.
//              Pete G.         4-aug-88        Minor revisions
*/


#include <exec/types.h>

#include "IPC.H"

#include <stdio.h>

#ifdef AZTEC_C
#include <functions.h>
#endif

#define  VERSION    "0.01"
#define  IPC_NAME   "MULT"
#define  BREAK_C    (1L<<12)

#define  ID_NUMBER  MAKE_ID('N','U','M','B')


/* ---------------------  Global Variables  -------------------------- */


struct IPCPort   *port;                        /* Our point of service */


/*  These functions to ensure proper type-casting
 *    have been moved into IPC.h for more general use [-- Pete --].
 *
 * #define GetIPCMessage(port) ((struct IPCMessage *)GetMsg(port))
 * #define ReplyIPCMessage(msg)  ReplyMsg(&(msg)->ipc_Msg)
 *
 *  [Pete also added in IPC.h:]
 *  SigBitIPCPort(port)
 *  -- a macro to return the signal bit of a port.
 */


/* ---------------------  The Code Beginneth  ------------------------ */


        void
work (mp)
        struct IPCMessage  *mp;
{
        register struct IPCItem     *items;
        long      n1, n2, p;

        items = & mp->ipc_Items[0];

        /* 1.  Check that types are OK: */
        if ((mp->ipc_ItemCount != 3) ||
                (items[1].ii_Id != ID_NUMBER) ||
                (items[1].ii_Size != 0) ||
                (items[2].ii_Id != ID_NUMBER) ||
                (items[2].ii_Size != 0) ||
                (items[0].ii_Size != 0) )       /* Make sure nothing attached here */
        {
                mp->ipc_Flags |= IPC_NOTKNOWN;
                return ;                /* BAD ! */
        }

        /* 2.  Do the work we came here for: */
        n1 = (long) items[1].ii_Ptr;
        n2 = (long) items[2].ii_Ptr;
        p = n1 * n2;

        /* 3.  Now store result, storing an indentifier: */
        items[0].ii_Id = ID_NUMBER;
        items[0].ii_Flags = IPC_MODIFIED | IPC_NETWORK;
 /*     items[0].ii_Size = 0L;  ** this is checked above */
        items[0].ii_Ptr = (void *) p;

        fprintf (stderr, "%s (%ld, %ld) --> %ld.\n", IPC_NAME, n1, n2, p);

}       /* work */


main ()
{
        struct IPCMessage   *msg;
        long  wait_flags, wake_flags;
        int   done = 0;

        fprintf (stderr, "[%s, %s]\n", IPC_NAME, VERSION);
        port = ServeIPCPort (IPC_NAME);
        if (port == NULL)
        {
                fprintf (stderr, "Some one already serving\n");
                exit (1);
        }

        wait_flags = BREAK_C | SigBitIPCPort(port);
        while (! done)
        {
                wake_flags = Wait (wait_flags);
                if (wake_flags & BREAK_C)
                {
                        /* Shutting the port here avoids having to drain port later! */
                ShutIPCPort (port);
                        done = 1;
                }

                while ((msg=GetIPCMessage(port)) != NULL)
                {
                        work (msg);                     /* Perform the work */
                        ReplyIPCMessage (msg);
                }

        }

        /*  Cleanup and Exit: */
        LeaveIPCPort (port);

        fprintf (stderr, "%s exiting..\n", IPC_NAME);
}       /* main */

