home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
488.lha
/
modengine_v1.0
/
mod_arexx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-03-07
|
8KB
|
285 lines
/* 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);
}