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