[alt.sources.amiga] ipc.manxdemos -- Manx demo programs for IPC.

amiga-sources@sugar.uu.net (alt.sources.amiga) (09/11/88)

Archive: uunet!~uucp/amiga-sources/ipc.manxdemos.Z

:
#! /bin/sh
# This is a shell archive, created on Sugar Land Unix (..!uunet!sugar)
# by amiga-sources (alt.sources.amiga) on Sun Sep 11 08:18:19 1988
# Remove anything before the "#! /bin/sh" line, then unpack it by saving
# it into a file and typing "sh file".  If you do not have sh, you need 
# unshar, a dearchiving program which is widely available.  In the absolute
# wost case, you can crack the files out by hand.
# If the archive is complete, you will see the message "End of archive."
# at the end.
# This archive contains the following files...
# 'READ_ME'
# 'IPC.h'
# 'makefile'
# 'Get.c'
# 'Have.c'
# To extract them, run the following through /bin/sh
echo x - READ_ME
sed 's/^X//' > READ_ME << '//END_OF_FILE'
X
X                Test programs for IPC using Manx C
X                ==================================
X
XThese two short programs "Get" and "Have" were written by Brian Witt to
Xtest out the IPC procedures under Manx/Aztec C.  I have taken the editorial
Xprerogative in a few places to make some slight changes, updates, and
Xcleanups. I haven't changed the functions of the programs at all (I hope!).
X
XThe Manx makefile is also included (but the necessary source IPC.c is in
Xthe IPC_Sources directory).  The programs also compile perfectly well under
XLattice; you should have no problem following the examples in demo_sources
Xto do the same thing here.
X
X"Have" accepts messages containing two integer items (in slots 2 and 3),
Xand returns their product in the first slot (initially empty).  Note that
Xit also prints the result in its window, so it should only be run from a
XCLI (and of course it must be a different one from "Get"!!).
X
X"Get" takes two numeric command-line arguments, puts them in a message,
Xsends it to "Have", and prints the result.  If you don't already have
X"Have" running, it will exit with a message to that effect.
X
XNotice that Brian has used a different ID 'NUMB' from my 'INTG': I haven't
Xchanged this, but this is the sort of conflict that needs sorting out in a
Xpublic standard -- hopefully over usenet.
X
X                                            -- Pete ---
X
X                                            August 1988
X
//END_OF_FILE
echo x - IPC.h
sed 's/^X//' > IPC.h << '//END_OF_FILE'
X/*******************************************************************
X *                                                                 *
X *                           IPC.h                                 *
X *                                                                 *
X *           Inter-Process-Communication Message Format            *
X *                                                                 *
X *              Revision 1.2.1 -- 1988 July 31                     *
X *                                                                 *
X *         Copyright 1988 Peter da Silva & Peter Goodeve           *
X *                      All Rights reserved                        *
X *                                                                 *
X *  This source is freely distributable, but should not be         *
X *  modified without prior consultation with the authors.          *
X *                                                                 *
X *******************************************************************/
X
X#ifdef AZTEC_C
X/* can't use prototyping */
X#define NARGS 1
X/* (if NARGS is undefined, prototyping is enabled) */
X#endif
X
X#ifndef EXEC_TYPES_H
X#include "exec/types.h"
X#endif
X
X#ifndef EXEC_PORTS_H
X#include "exec/ports.h"
X#endif
X
X/*** Item Reference block -- an arbitrary number of these may be
X   put in an IPCMessage ***/
X
Xstruct IPCItem {
X    ULONG   ii_Id;      /* four character ID (normally);
X                           determines exact meaning of IPCItem IDs */
X    ULONG   ii_Flags;   /* upper 16 bits have standard meaning;
X                           lower 16 bits are message dependent */
X    ULONG   ii_Size;    /* size of data structure (zero if ii_Ptr is not
X                           actually a pointer to data) */
X    void   *ii_Ptr;     /* points to defined data structure (could be within
X                           message block if IE_Flags says so) -- also may be
X                           recast to other 32-bit value (e.g. Lock) */
X    };
X
X
X
X/*** The basic IPCMessage block ***/
X
Xstruct IPCMessage {
X    struct Message  ipc_Msg;
X        /* ..ln_Name field should be NULL
X            mn_Length will include IPC_Items array and any in-line data
X        */
X    ULONG   ipc_Id,                /* four character (or other) ID */
X            ipc_Flags;
X    UWORD   ipc_ItemCount;         /* number of items in array */
X    struct  IPCItem ipc_Items[1];  /* .. actual size as needed */
X    };
X
X
X/*************************************************************/
X
X/* Flags set by client (tentative...): */
X/* -- may appear in either IPCItem or IPCMessage Flags field */
X
X#define IPC_TRANSFER   0x08000000
X    /* Data block ownership is to be transferred to receiver. */
X#define IPC_NETWORK    0x04000000
X    /* The data in this block/message may be transmitted to
X       another machine */
X#define IPC_INMESSAGE  0x02000000
X    /* The data in this block/message is included in the message length */
X
X/* Flags returned by server (ditto): */
X
X#define IPC_NOTKNOWN   0x80000000
X    /* The server could not handle this block/message
X       (either because it did not understand the ID or
X       was unable to process it -- see the secondary flags */
X#define IPC_MODIFIED   0x40000000
X    /* The server modified the data, either within the
X       supplied data block(s) or -- if permitted -- by
X       replacing/removing the block pointer; again maybe
X       other flag bits should indicate the nature of
X       the modification */
X
X/* valid for Item only: */
X#define IPC_SERVER_OWNED 0x10000000
X    /* The server owns this data Item -- either because it has
X       created it or because it took it over from the client
X       (in which case it clears IPC_TRANSFER, which must have
X       been set) */
X
X
X/* secondary flag bits (more to come...): */
X
X#define IPC_CHECKITEM 0x00800000
X    /* associated with IPC_NOTKNOWN -- indicates that one or more
X       particular items caused the flag to be set */
X#define IPC_FAILED 0x00400000
X    /* IPC_NOTKNOWN flag was set because the server failed to
X       handle an ID that it is designed to (rather than just
X       not recognizing the block) */
X
X/*************************************************************/
X
X
X/*** IPC Ports and Procedures ***/
X
X
X/* -- see IPCPorts.h for actual structure definitions */
X#ifndef IPC_PORTS_H
X/* Normal user doesn't need access to port components,
X   so just use a convenient define.  Note that an IPC port
X   is NEVER in private data space -- or in the public port
X   list -- it is created and managed by the package routines
X   only. */
X#define IPCPort MsgPort
X#endif
X
X
X/* IPC Port Handling function prototypes: */
X
X#ifndef NARGS /* define this to SUPPRESS function argument prototyping */
X
Xstruct IPCPort * FindIPCPort(char *);
X    /* returns pointer to port if it exists -- null otherwise;
X       registers a new connection to the port */
X
Xstruct IPCPort * GetIPCPort(char *);
X    /* returns pointer to port -- it is created if it doesn't exist;
X       registers a new connection to the port */
X
X
Xvoid UseIPCPort(struct IPCPort *);
X    /* adds a connection to a port (passed by pointer from another
X       process) */
X
X
Xvoid DropIPCPort(struct IPCPort *);
X    /* disconnect from port -- port will be destroyed if there are
X       no other connections left */
X
X
Xstruct IPCPort * ServeIPCPort(char *);
X    /* become a server for the named port (created if it doesn't exist);
X       null is returned if the port already has a server, otherwise a
X       pointer to it is returned */
X
Xvoid ShutIPCPort(struct IPCPort *);
X    /* (server only) prevent more messages being sent to this port, but
X       do not end server connection; remaining messages can be dealt
X       with before Leaving */
X
Xvoid LeaveIPCPort(struct IPCPort *);
X    /* cease to be a server for this port; another process can then
X       become a server if it desires */
X
XCheckIPCPort(struct IPCPort *, UWORD);
X    /* returns number of current connections to this port (including
X       server); a call by the server (only) will also set the (user
X       settable) port flags to the value in the second argument --
X       currently the only valid flag is IPP_NOTIFY */
X
X
XPutIPCMsg(struct IPCPort *, struct IPCMessage *);
X    /* sends an IPCMessage to an IPCPort; if the port has no server or
X       is shut, the message is not sent and the function returns FALSE;
X       otherwise it returns TRUE. (Other port flags to be added later
X       may affect these actions.) */
X
Xstruct IPCMessage * CreateIPCMsg(int, int, struct MsgPort *);
X    /* creates a standard IPCMessage block (in MEMF_PUBLIC) with the
X       number of IPCItems supplied as first argument;  the second
X       argument is the number of bytes -- if any -- to reserve beyond
X       that required for the items; the third is a pointer to the
X       ReplyPort (may be NULL -- note that it's a standard MsgPort,
X       not an IPCPort). (You always have to manage any data
X       blocks yourself). */
X
X
Xvoid DeleteIPCMsg(struct IPCMessage *);
X    /* deletes a standard IPCMessage block;  you must first have disposed
X       of any attached data as appropriate */
X
X/*************************************************************/
X#else NARGS defined
X
Xstruct IPCPort * FindIPCPort ();
Xstruct IPCPort * GetIPCPort ();
Xvoid             UseIPCPort ();
Xvoid             DropIPCPort ();
Xstruct IPCPort * ServeIPCPort ();
Xvoid             ShutIPCPort ();
Xvoid             LeaveIPCPort ();
Xint              CheckIPCPort ();
Xint              PutIPCMsg ();
Xstruct IPCMessage * CreateIPCMsg ();
Xvoid             DeleteIPCMsg ();
X
X/*************************************************************/
X#endif NARGS
X
X
X/* System IPCPort flags: */
X
X#define IPP_SERVED 0x8000
X    /* port currently has a server */
X#define IPP_SHUT 0x4000
X    /* port is no longer open for new messages (server still attached) */
X#define IPP_REOPEN 0x2000
X    /* set (by "Port Broker") to request that server reopen service
X       to this port after it has completed Shut/Leave sequence
X       in progress */
X#define IPP_LOADING 0x1000
X    /* set (by "Port Broker") to indicate that a server is being loaded
X       for this port (cleared by ServeIPCPort()) */
X
X
X/* Server settable Port flags: */
X
X#define IPP_NOTIFY 0x0001
X    /* server wants to be signalled if connection is added or
X       dropped (the port sigbit is used to signal the task,
X       but no message is sent) */
X
X/*************************************************************/
X
X/*
X *  Some useful Macros:
X */
X
X#define GetIPCMessage(port) ((struct IPCMessage *)GetMsg((struct MsgPort *)port))
X
X#define ReplyIPCMessage(msg)  ReplyMsg((struct Message *)msg)
X
X#define SigBitIPCPort(port) (1<<((struct MsgPort *)port)->mp_SigBit)
X    /* note: this will work whether or not IPCPorts.h has been included */
X
X
X/*
X   For convenience in creating IDs:
X    (Alternatively, your compiler may have multi-character constants,
X     which you may find more convenient (but less portable...))
X*/
X
X#define MAKE_ID(a,b,c,d) ((a)<<24L | (b)<<16L | (c)<<8 | (d))
X
X
//END_OF_FILE
echo x - makefile
sed 's/^X//' > makefile << '//END_OF_FILE'
X#######################
X#       :bk=0
X#       Test suite for Peter/Pete IPC system
X#       Creates GET and HAVE.
X#
X#       bjw             25-june-88      Initial coding.
X#
X
XOBJS = have.o get.o ipc.o
XCFLAGS = +Q
X
X#
X# --- Give me a reference:
X#
Xstone:  have get
X        @touch stone
X
Xhave:   have.o ipc.o
X        ln -o HAVE  have.o ipc.o -lc
X
Xget:    get.o ipc.o
X        ln -o GET   get.o  ipc.o -lc
X
X#
X# --- Now the source files:
X#
Xipc.o:  ipc.h ipcports.h
X        cc $(CLFAGS) -o ipc.o IPC.C
X        diff >ipc-c.diff IPC.C df1:IPC.C
X        diff >ipc-h.diff IPC.H df1:IPC.H
X
X$(OBJS):        ipc.h ipcports.h
X
X
//END_OF_FILE
echo x - Get.c
sed 's/^X//' > Get.c << '//END_OF_FILE'
X/*   GET.C     Client for Peter/Pete's IPC system.        bjw  june 88 */
X
X/*
X//              This client requests the function of multiplication:
X//              You pass two numbers, the result is their product.  This is
X//              meant to be a pseduo-test suite for the Manx IPC product.
X//              Reads numbers from command line only.
X//
X//              bjw             25-june-88      Initial coding.
X//              Pete G.         4-aug-88        Revisions
X//
X//  [In my capacity as "editor", I've taken the liberty of making several
X//   changes in Brian's original, for various necessary reasons.  I hope
X/    he'll forgive me.   -- Pete --]
X*/
X
X
X#include <exec/types.h>
X
X#include "IPC.H"
X
X#include <stdio.h>
X
X#ifdef AZTEC_C
X#include <functions.h>
X#endif
X
X#define  VERSION    "0.02"
X#define  IPC_NAME   "MULT"
X
X#define  ID_NUMBER  MAKE_ID('N','U','M','B')
X
Xextern long  atol ();
X
X
X/* ---------------------  Global Variables  -------------------------- */
X
X
Xstruct IPCPort   *port;                       /* Our point of service */
Xstruct MsgPort   *reply;
X
X
X/* ----------------------  Primitive Code  --------------------------- */
X
XfillItem (item, number)
X        struct IPCItem  *item;
X        long   number;
X{
X
X        item->ii_Id = ID_NUMBER;
X        item->ii_Flags = IPC_TRANSFER | IPC_NETWORK;
X        item->ii_Size = 0;
X        item->ii_Ptr = (void *) number;
X}
X
X
X/* ---------------------  The Code Beginneth  ------------------------ */
X
X/*
X *  This procedure sends a single message
X */
X        long
Xsend (str1, str2)
X        char  *str1, *str2;
X{
X        register struct IPCMessage   *msg;
X        long   n1, n2;
X        long   res;
X
X        n1 = atol (str1);
X        n2 = atol (str2);
X
X        msg = CreateIPCMsg (3, 0, reply);
X        if (!msg) return -1;
X
X        msg->ipc_Items[0].ii_Size = 0;          /* Server provides result here */
X        fillItem (& msg->ipc_Items[1], n1);
X        fillItem (& msg->ipc_Items[2], n2);
X
X        if (PutIPCMsg (port, msg)) /* MUST always check that it got sent! */
X            WaitPort (reply);               /* Get the reply */
X
X        if (((msg->ipc_Flags & IPC_NOTKNOWN) == 0) &&
X                (msg->ipc_Items[0].ii_Flags & IPC_MODIFIED) )
X        {
X                res = (long) msg->ipc_Items[0].ii_Ptr;
X        } else
X        {
X                res = -1;
X        }
X
X        DeleteIPCMsg (msg);
X
X        return (res);
X}       /* send */
X
X
Xvoid Getout(exitcode) int exitcode;
X{
X    if (port) DropIPCPort(port);
X    if (reply) DeletePort(reply);
X    exit(exitcode);
X}
X
X
X
Xmain (argc, argv)
X        int  argc;
X        char *argv[];
X{
X        long   res;
X
X        fprintf (stderr, "[Use %s, %s]\n", IPC_NAME, VERSION);
X
X        if (argc != 3)
X        {
X                fprintf (stderr, "usage: get <numb1> <numb2>\n");
X                fprintf (stderr, "\tprint product of two numbers\n");
X                exit (1);
X        }
X
X        port = FindIPCPort (IPC_NAME);
X        /* [In most cases GetIPCPort is preferable, so that you don't
X            have to have a server already loaded, but this client sends
X            its message the moment it is called, so FindIPCPort is
X            appropriate   -- Pete --]
X        */
X        if (port == NULL)
X        {
X                fprintf (stderr, "Can't find server.\n");
X                Getout(1);
X        }
X
X        reply = CreatePort (0L, NULL);
X        if (!reply) Getout(1);
X
X        res = send (argv[1], argv[2]);
X
X        printf ("%s (%s,%s) --> %ld\n", IPC_NAME, argv[1], argv[2], res);
X
X        Getout(0);
X
X}       /* main */
//END_OF_FILE
echo x - Have.c
sed 's/^X//' > Have.c << '//END_OF_FILE'
X/*   HAVE.C     Server for Peter/Pete's IPC system.        bjw  june 88 */
X
X/*
X//              This server provides the function of multiplication:
X//              You pass two numbers, the result is their product.  This is
X//              meant to be a pseudo-test suite for the Manx IPC product.
X//              Send us a BREAK C to cause us to exit.
X//
X//              bjw             25-june-88      Initial coding.
X//              Pete G.         4-aug-88        Minor revisions
X*/
X
X
X#include <exec/types.h>
X
X#include "IPC.H"
X
X#include <stdio.h>
X
X#ifdef AZTEC_C
X#include <functions.h>
X#endif
X
X#define  VERSION    "0.01"
X#define  IPC_NAME   "MULT"
X#define  BREAK_C    (1L<<12)
X
X#define  ID_NUMBER  MAKE_ID('N','U','M','B')
X
X
X/* ---------------------  Global Variables  -------------------------- */
X
X
Xstruct IPCPort   *port;                        /* Our point of service */
X
X
X/*  These functions to ensure proper type-casting
X *    have been moved into IPC.h for more general use [-- Pete --].
X *
X * #define GetIPCMessage(port) ((struct IPCMessage *)GetMsg(port))
X * #define ReplyIPCMessage(msg)  ReplyMsg(&(msg)->ipc_Msg)
X *
X *  [Pete also added in IPC.h:]
X *  SigBitIPCPort(port)
X *  -- a macro to return the signal bit of a port.
X */
X
X
X/* ---------------------  The Code Beginneth  ------------------------ */
X
X
X        void
Xwork (mp)
X        struct IPCMessage  *mp;
X{
X        register struct IPCItem     *items;
X        long      n1, n2, p;
X
X        items = & mp->ipc_Items[0];
X
X        /* 1.  Check that types are OK: */
X        if ((mp->ipc_ItemCount != 3) ||
X                (items[1].ii_Id != ID_NUMBER) ||
X                (items[1].ii_Size != 0) ||
X                (items[2].ii_Id != ID_NUMBER) ||
X                (items[2].ii_Size != 0) ||
X                (items[0].ii_Size != 0) )       /* Make sure nothing attached here */
X        {
X                mp->ipc_Flags |= IPC_NOTKNOWN;
X                return ;                /* BAD ! */
X        }
X
X        /* 2.  Do the work we came here for: */
X        n1 = (long) items[1].ii_Ptr;
X        n2 = (long) items[2].ii_Ptr;
X        p = n1 * n2;
X
X        /* 3.  Now store result, storing an indentifier: */
X        items[0].ii_Id = ID_NUMBER;
X        items[0].ii_Flags = IPC_MODIFIED | IPC_NETWORK;
X /*     items[0].ii_Size = 0L;  ** this is checked above */
X        items[0].ii_Ptr = (void *) p;
X
X        fprintf (stderr, "%s (%ld, %ld) --> %ld.\n", IPC_NAME, n1, n2, p);
X
X}       /* work */
X
X
Xmain ()
X{
X        struct IPCMessage   *msg;
X        long  wait_flags, wake_flags;
X        int   done = 0;
X
X        fprintf (stderr, "[%s, %s]\n", IPC_NAME, VERSION);
X        port = ServeIPCPort (IPC_NAME);
X        if (port == NULL)
X        {
X                fprintf (stderr, "Some one already serving\n");
X                exit (1);
X        }
X
X        wait_flags = BREAK_C | SigBitIPCPort(port);
X        while (! done)
X        {
X                wake_flags = Wait (wait_flags);
X                if (wake_flags & BREAK_C)
X                {
X                        /* Shutting the port here avoids having to drain port later! */
X                ShutIPCPort (port);
X                        done = 1;
X                }
X
X                while ((msg=GetIPCMessage(port)) != NULL)
X                {
X                        work (msg);                     /* Perform the work */
X                        ReplyIPCMessage (msg);
X                }
X
X        }
X
X        /*  Cleanup and Exit: */
X        LeaveIPCPort (port);
X
X        fprintf (stderr, "%s exiting..\n", IPC_NAME);
X}       /* main */
X
//END_OF_FILE
echo "End of archive."
# end of archive.
exit 0