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