home *** CD-ROM | disk | FTP | other *** search
- /* mod_arexx.c
- * Copyright (C) 1990 Commodore-Amiga, Inc.
- * written by David N. Junod
- *
- * AREXX message handling routines
- *
- */
-
- #include "mod.h"
-
- /* variables required for ARexx */
- struct ARexxInfo
- {
- struct MsgPort *rxport; /* ARexx message port */
- UBYTE *portname; /* ARexx message port name */
- UBYTE *extens; /* ARexx macro name extension */
- BOOL astatus; /* ARexx status */
-
- /* user call-back functions */
- VOID (*ufunc[2])(struct AppInfo *, struct Message *, struct MsgHandler *);
- };
-
- /* User call-back function pointers */
- #define ARX_MACRO_ERROR 0
- #define ARX_MACRO_GOOD 1
-
- /* ARexx message handling routines */
- BOOL open_arexx (struct AppInfo *, struct MsgHandler * );
- BOOL handle_arexx (struct AppInfo *, struct MsgHandler * );
- BOOL close_arexx (struct AppInfo *, struct MsgHandler * );
- BOOL shutdown_arexx (struct AppInfo *, struct MsgHandler * );
-
- BOOL send_rexx_command (UBYTE *, struct AppInfo *, struct MsgHandler *);
- VOID execute_command (struct RexxMsg *,struct AppInfo *,struct MsgHandler *);
- VOID reply_rexx_command (struct RexxMsg *,struct AppInfo *,struct MsgHandler *);
-
- /* ARexx Functions Prototypes */
- struct RexxMsg *CreateRexxMsg (struct MsgPort *, UBYTE *, UBYTE *);
- STRPTR CreateArgstring (UBYTE *, int);
- VOID DeleteRexxMsg (struct RexxMsg *);
- VOID DeleteArgstring (UBYTE *);
- BOOL IsRexxMsg (struct Message *);
-
- /* Required for ARexx processing */
- struct RxsLib *RexxSysBase = NULL;
-
- struct MsgHandler *setup_arexx (struct AppInfo * ai, UBYTE * pname,
- UBYTE * extens, BOOL immed)
- {
- UBYTE *portname = " ";
- register WORD cntr = 1;
- BOOL exist = TRUE, retval = FALSE;
- struct MsgHandler *mh = NULL;
- struct ARexxInfo *md = NULL;
-
- if (md = (struct ARexxInfo *)
- AllocMem (sizeof (struct ARexxInfo), MEMF_CLEAR|MEMF_PUBLIC))
- {
- md->portname = pname;
- md->extens = extens;
- if (RexxSysBase = (struct RsxLib *)
- OpenLibrary ("rexxsyslib.library", 0L))
- {
-
- /* forbid multi-tasking while we try to get a port */
- Forbid ();
-
- /* get an unique port name */
- while (exist)
- {
- /* create a name with our base name and a number */
- sprintf (portname, "%s_%d", md->portname, cntr);
-
- /* see if someone has already taken this name */
- if (!FindPort (portname))
- exist = FALSE;
- cntr++;
- }
-
- /* allocate the port */
- if (md->rxport = CreatePort (portname, 0L))
- retval = TRUE;
-
- /* permit multi-tasking again */
- Permit ();
-
- if (mh = (struct MsgHandler *)
- AllocMem (sizeof (struct MsgHandler), MEMF_CLEAR|MEMF_PUBLIC))
- {
- mh->mh_Node.ln_Type = MH_HANDLER_T;
- mh->mh_Node.ln_Pri = MH_HANDLER_P;
- mh->mh_Node.ln_Name = "AREXX";
- mh->mh_SigBits = (1L << md->rxport->mp_SigBit);
- mh->mh_Func[MH_OPEN] = open_arexx;
- mh->mh_Func[MH_HANDLE] = handle_arexx;
- mh->mh_Func[MH_CLOSE] = close_arexx;
- mh->mh_Func[MH_SHUTDOWN] = shutdown_arexx;
- mh->mh_Data = md;
-
- /* open immediately? */
- if (immed)
- {
- if (open_arexx (ai, mh))
- return (mh);
- }
- else
- return (mh);
-
- FreeMem (mh, sizeof (struct MsgHandler));
- }
- else
- NotifyUser (NULL, "Not enough memory");
-
- /* make a nice clean failure path */
- DeletePort (md->rxport);
- CloseLibrary ((struct Library *) RexxSysBase);
- md->rxport = NULL;
- RexxSysBase = NULL;
- }
- else
- NotifyUser (NULL, "Could not open rexxsyslib.library");
-
- FreeMem (md, sizeof (struct ARexxInfo));
- }
- return (mh);
- }
-
- BOOL open_arexx (struct AppInfo * ai, struct MsgHandler * mh)
- {
- ((struct ARexxInfo *)mh->mh_Data)->astatus = AR_EXECUTE;
- return (TRUE);
- }
-
- /* ARexx message processing */
- BOOL handle_arexx (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct RexxMsg *rmsg; /* incoming ARexx messages */
- struct ARexxInfo * md = mh->mh_Data;
-
- while (rmsg = (struct RexxMsg *) GetMsg (md->rxport))
- {
- if (rmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
- {
- /* This is a reply to a previous message */
- if (rmsg->rm_Result1)
- {
- /* returned an error message, perform user call-back */
- if (md->ufunc[ARX_MACRO_ERROR])
- (*md->ufunc[ARX_MACRO_ERROR])
- (ai, (struct Message *) rmsg, mh);
- }
- else
- {
- /* successful return, perform user call-back */
- if (md->ufunc[ARX_MACRO_GOOD])
- (*md->ufunc[ARX_MACRO_GOOD])
- (ai, (struct Message *) rmsg, mh);
- }
- /* delete the argument that we originally sent */
- DeleteArgstring (rmsg->rm_Args[0]);
-
- /* delete the extended message */
- DeleteRexxMsg (rmsg);
-
- /* decrement the count of outstanding messages */
- ai->numcmds--;
- }
- else
- /* We have received a command/function message */
- execute_command (rmsg, ai, mh);
- }
- return (TRUE);
- }
-
- BOOL close_arexx (struct AppInfo * ai, struct MsgHandler * mh)
- {
- ((struct ARexxInfo *)mh->mh_Data)->astatus = AR_SUSPEND;
- return (TRUE);
- }
-
- BOOL shutdown_arexx (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct ARexxInfo * md = mh->mh_Data;
-
- if (mh)
- {
- if (md->rxport)
- DeletePort (md->rxport);
-
- Remove ((struct Node *) mh);
- FreeMem (mh, sizeof (struct MsgHandler));
- }
- if (RexxSysBase)
- CloseLibrary ((struct Library *) RexxSysBase);
- RexxSysBase = NULL;
- return (TRUE);
- }
-
- BOOL send_rexx_command (UBYTE * buff, struct AppInfo * ai,
- struct MsgHandler * mh)
- {
- struct MsgPort *rexxport; /* this will be rexx's port */
- struct RexxMsg *rexx_command_message; /* this is the message */
- struct ARexxInfo * md = mh->mh_Data;
-
- /* lock things temporarily */
- Forbid ();
-
- /* if ARexx is not active, just return FALSE */
- if (!(rexxport = FindPort (RXSDIR)))
- {
- Permit ();
- return (FALSE);
- }
-
- /* allocate a message packet for our command */
- /* note that this is a very important call. Much flexibility is */
- /* available to you here by using multiple host port names, etc. */
- if (!(rexx_command_message = CreateRexxMsg (md->rxport,
- md->extens,
- md->rxport->mp_Node.ln_Name)))
- {
- Permit ();
- return (FALSE);
- }
-
- /* create an argument string and install it in the message */
- if (!(rexx_command_message->rm_Args[0] =
- CreateArgstring (buff, strlen (buff))))
- {
- DeleteRexxMsg (rexx_command_message);
- Permit ();
- return (FALSE);
- }
-
- /* indicate that message is a command */
- rexx_command_message->rm_Action = RXCOMM;
-
- /* send the message */
- PutMsg (rexxport, (struct Message *) rexx_command_message);
-
- /* increment the number of outstanding messages */
- ai->numcmds++;
-
- Permit ();
- return (TRUE);
- }
-
- VOID execute_command (struct RexxMsg * rmsg, struct AppInfo * ai,
- struct MsgHandler * mh)
- {
- struct ARexxInfo * md = mh->mh_Data;
- UBYTE *cmd = ARG0 (rmsg);
-
- /* preset the ARexx error return values */
- ai->pri_ret = 5L;
- ai->sec_ret = 0L;
- ai->textrtn = NULL;
-
- /* Don't perform function if we are suspended */
- if (md->astatus == AR_EXECUTE)
- PerfFunc (ai, (struct Message *) rmsg, cmd);
- else
- ai->pri_ret = 100L;
-
- /* reply to the message */
- reply_rexx_command (rmsg, ai, mh);
- }
-
- /* Replys to a ARexx message */
- VOID reply_rexx_command (struct RexxMsg * rmsg, struct AppInfo * ai,
- struct MsgHandler * mh)
- {
- /* set an error code */
- if (ai->pri_ret == 0 && (rmsg->rm_Action & 1L << RXFB_RESULT))
- {
- ai->sec_ret = ai->textrtn ?
- (LONG) CreateArgstring (ai->textrtn, strlen (ai->textrtn))
- : (LONG) NULL;
- }
- rmsg->rm_Result1 = ai->pri_ret;
- rmsg->rm_Result2 = ai->sec_ret;
- ReplyMsg ((struct Message *) rmsg);
- }
-