home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
libraries
/
rexxhostlib_403
/
rexxhostlib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-17
|
15KB
|
729 lines
/* $Revision Header * Header built automatically - do not edit! *************
*
* (C) Copyright 1990 by MXM
*
* Name .....: RexxHostLib.c
* Created ..: Sunday 07-Jan-90 18:55
* Revision .: 14
*
* Date Author Comment
* ========= ======== ====================
* 09-Sep-90 Olsen Bug fixed in GetToken, added
* IsSpace() and GetRexxClip()
* 24-May-90 Olsen General rewrite, added new functions
* 26-Apr-90 Olsen Supports short integers (16 bits)
* 13-Apr-90 Olsen Added assembly language routines
* 31-Mar-90 Olsen Rewrote RexxStrCmp
* 19-Mar-90 Olsen More sanity checks
* 17-Mar-90 Olsen Added RexxStrCmp, rewrote
* CreateRexxHost/DeleteRexxHost,
* ANSIfication
* 16-Mar-90 Olsen Rework for Aztec 5.0 release
* 07-Jan-90 Olsen Added string conversion functions
* 07-Jan-90 Olsen Added GetToken
* 07-Jan-90 Olsen - Empty log message -
* 07-Jan-90 Olsen Removed bug in SendRexxCommand
* 07-Jan-90 Olsen - Empty log message -
* 07-Jan-90 Olsen Created this file!
*
****************************************************************************
*
* This Amiga shared library is based on example source code
* written by Gary Samad & Bill Hawes.
*
* $Revision Header ********************************************************/
#define REVISION 14
/* Main rexx library base. */
extern struct RxsLib *RexxSysBase;
/* Global revision identifier. */
LONG Revision = REVISION;
/* CreateRexxHost(HostName):
*
* Creates a RexxHost (special MsgPort) with a given name.
* Returns NULL if port already exists.
*/
struct RexxHost *
CreateRexxHost(STRPTR HostName)
{
struct RexxHostBase *RexxHostBase;
struct RexxHost *RexxHost;
/* Valid name given? */
if(HostName && HostName[0])
{
/* Already present? */
if(!FindPort((char *)HostName))
{
/* Allocate the port body. */
if(RexxHost = (struct RexxHost *)AllocMem(sizeof(struct RexxHost),MEMF_PUBLIC | MEMF_CLEAR))
{
/* Allocate a signal bit. */
if((RexxHost -> rh_Port . mp_SigBit = AllocSignal(-1)) != -1)
{
/* Initialize the MsgPort node head. */
RexxHost -> rh_Port . mp_Node . ln_Type = NT_MSGPORT;
RexxHost -> rh_Port . mp_Node . ln_Pri = 1;
/* Allocate memory for MsgPort name. */
if(RexxHost -> rh_Port . mp_Node . ln_Name = (char *)AllocMem(StrLen((char *)HostName) + 1,MEMF_PUBLIC))
{
/* Copy the name. */
StrCpy(RexxHost -> rh_Port . mp_Node . ln_Name,(char *)HostName);
/* Deal with the rest of the flags. */
RexxHost -> rh_Port . mp_Flags = PA_SIGNAL;
RexxHost -> rh_Port . mp_SigTask = SysBase -> ThisTask;
/* A dummy ID. */
RexxHost -> rh_SpecialID = 'REXX';
/* Finally add it to the public port list. */
AddPort(&RexxHost -> rh_Port);
/* And return it to the caller. */
return(RexxHost);
}
FreeSignal(RexxHost -> rh_Port . mp_SigBit);
}
FreeMem(RexxHost,sizeof(struct RexxHost));
}
}
}
return(NULL);
}
/* DeleteRexxHost(RexxHost):
*
* Deletes a MsgPort as created by CreateRexxHost().
* Returns NULL, so user can do 'Host = DeleteRexxHost(Host);'.
*/
VOID *
DeleteRexxHost(struct RexxHost *RexxHost)
{
struct RexxHostBase *RexxHostBase;
/* Valid host port given? */
if(RexxHost && RexxHost -> rh_SpecialID == 'REXX')
{
/* Remove it from the public list. */
RemPort(&RexxHost -> rh_Port);
/* Free the name. */
FreeMem(RexxHost -> rh_Port . mp_Node . ln_Name,StrLen(RexxHost -> rh_Port . mp_Node . ln_Name) + 1);
/* Free the allocated signal bit. */
FreeSignal(RexxHost -> rh_Port . mp_SigBit);
/* Free the body. */
FreeMem(RexxHost,sizeof(struct RexxHost));
}
return(NULL);
}
/* SendRexxCommand(HostPort,CommandString,FileExtension,HostName):
*
* Sends a command to the rexx server, requires pointers
* to the MsgPort of the calling Host and the command string.
* File extension and host name are optional and may be
* NULL.
*/
LONG
SendRexxCommand(struct RexxHost *HostPort,STRPTR CommandString,STRPTR FileExtension,STRPTR HostName)
{
struct RexxHostBase *RexxHostBase;
struct MsgPort *RexxPort = (struct MsgPort *)FindPort(RXSDIR);
struct RexxMsg *HostMessage;
/* Valid pointers given? */
if(CommandString && HostPort && HostPort -> rh_SpecialID == 'REXX' && RexxPort)
{
/* No special host name given? Take the MsgPort name. */
if(!HostName)
HostName = (STRPTR)HostPort -> rh_Port . mp_Node . ln_Name;
/* No file name extension? Take the default. */
if(!FileExtension)
FileExtension = (STRPTR)"rexx";
/* Create the message. */
if(HostMessage = CreateRexxMsg((struct MsgPort *)HostPort,(char *)FileExtension,(char *)HostName))
{
/* Add the command. */
if(HostMessage -> rm_Args[0] = CreateArgstring((char *)CommandString,StrLen((char *)CommandString)))
{
/* This is a command, not a function. */
HostMessage -> rm_Action = RXCOMM;
/* Release it... */
PutMsg(RexxPort,HostMessage);
/* Successful action. */
return(TRUE);
}
DeleteRexxMsg(HostMessage);
}
}
return(FALSE);
}
/* FreeRexxCommand(RexxMessage):
*
* Frees the contents of a RexxMsg.
*/
VOID
FreeRexxCommand(struct RexxMsg *RexxMessage)
{
struct RexxHostBase *RexxHostBase;
/* Valid pointer given? */
if(RexxMessage && RexxMessage -> rm_Node . mn_Node . ln_Type == NT_REPLYMSG)
{
/* Remove argument. */
if(RexxMessage -> rm_Args[0])
DeleteArgstring((char *)RexxMessage -> rm_Args[0]);
/* Free the message. */
DeleteRexxMsg(RexxMessage);
}
}
/* ReplyRexxCommand(RexxMessage,Primary,Secondary,Result):
*
* Sends a RexxMsg back to the rexx server, can include
* result codes.
*/
VOID
ReplyRexxCommand(struct RexxMsg *RexxMessage,LONG Primary,LONG Secondary,STRPTR Result)
{
struct RexxHostBase *RexxHostBase;
/* Valid pointer given? */
if(RexxMessage && RexxMessage -> rm_Node . mn_Node . ln_Type == NT_MESSAGE)
{
/* No secondary result and results wanted? */
if(Secondary == NULL && (RexxMessage -> rm_Action & RXFF_RESULT))
{
/* Build result string... */
if(Result)
Secondary = (LONG)CreateArgstring((char *)Result,StrLen((char *)Result));
}
/* Set both results... */
RexxMessage -> rm_Result1 = Primary;
RexxMessage -> rm_Result2 = Secondary;
/* ...and reply the message. */
ReplyMsg(RexxMessage);
}
}
/* GetRexxCommand(RexxMessage):
*
* Returns a pointer to the command string if
* the RexxMsg is a command request.
*/
STRPTR
GetRexxCommand(struct RexxMsg *RexxMessage)
{
struct RexxHostBase *RexxHostBase;
if(!RexxMessage || RexxMessage -> rm_Node . mn_Node . ln_Type == NT_REPLYMSG)
return(NULL);
else
return(RexxMessage -> rm_Args[0]);
}
/* GetRexxArg(RexxMessage):
*
* Returns a pointer to the first RexxMsg argument.
*/
STRPTR
GetRexxArg(struct RexxMsg *RexxMessage)
{
struct RexxHostBase *RexxHostBase;
if(!RexxMessage)
return(NULL);
else
return(RexxMessage -> rm_Args[0]);
}
/* GetRexxResult1(RexxMessage):
*
* Returns the 1st RexxMsg result.
*/
LONG
GetRexxResult1(struct RexxMsg *RexxMessage)
{
struct RexxHostBase *RexxHostBase;
if(!RexxMessage)
return(NULL);
else
return(RexxMessage -> rm_Result1);
}
/* GetRexxResult2(RexxMessage):
*
* Returns the 2nd RexxMsg result.
*/
LONG
GetRexxResult2(struct RexxMsg *RexxMessage)
{
struct RexxHostBase *RexxHostBase;
if(!RexxMessage)
return(NULL);
else
return(RexxMessage -> rm_Result2);
}
/* IsSpace():
*
* Returns TRUE if the input character is a space, tab,
* carriage return, newline, form feed or vertical tab.
*/
STATIC BYTE
IsSpace(UBYTE c)
{
if((c >= 13 && c <= 17) || c == 32)
return(TRUE);
else
return(FALSE);
}
/* GetToken(String,StartChar,AuxBuff,MaxLength):
*
* Fills a string with the next given string
* argument.
*/
STRPTR
GetToken(STRPTR String,LONG *StartChar,STRPTR AuxBuff,LONG MaxLength)
{
struct RexxHostBase *RexxHostBase;
SHORT i,StrEnd = 0,MaxPos = StrLen((char *)String);
/* Last counter position. */
if(MaxPos >= MaxLength + *StartChar)
MaxPos = MaxLength + *StartChar - 1;
/* Already finished with argument string? */
if(*StartChar <= StrLen((char *)String) - 1 && String && String[0] && AuxBuff && MaxLength)
{
/* Parse the argument string... */
for(i = *StartChar ; i <= MaxPos ; i++)
{
/* Skip leading blanks... */
if(!StrEnd && IsSpace(String[i]))
{
while(IsSpace(String[i]) && i < MaxPos)
{
i++;
(*StartChar)++;
}
}
/* Found an argument. */
if(IsSpace(String[i]) || String[i] == 0)
{
/* Copy it to the auxiliary buffer. */
StrNCpy((char *)AuxBuff,(char *)(String + *StartChar),StrEnd);
AuxBuff[StrEnd] = 0;
/* Change the position counter (since
* we can't use static data initialisation
* calling program has to supply a
* counter variable).
*/
(*StartChar) += StrEnd;
return(AuxBuff);
}
/* Increment character counter. */
StrEnd++;
}
}
return(NULL);
}
/* GetStringValue(String):
*
* Returns the numeric value taken from given string
* (just like atoi(), taken from example source code
* by K&R).
*/
LONG
GetStringValue(STRPTR String)
{
struct RexxHostBase *RexxHostBase;
LONG Value;
BYTE Sign = 1;
SHORT i;
/* Valid argument given? */
if(String && !String[0])
{
/* Skip leading blank characters. */
for(i = 0 ; String[i] == ' ' || String[i] == '\n' || String[i] == '\t' ; i++);
/* Remember sign extension. */
if(String[i] == '+' || String[i] == '-')
Sign = (String[i++] == '+') ? 1 : -1;
/* Convert from ASCII to decimal. */
for(Value = 0 ; String[i] >= '0' && String[i] <= '9' ; i++)
Value = 10 * Value + String[i] - '0';
/* Return real value. */
return(Sign * Value);
}
return(0);
}
/* BuildValueString(Value,String):
*
* Puts a numeric value in decimal form into a
* given string (similar to itoa(), taken from
* example source code by K&R).
*/
STRPTR
BuildValueString(LONG Value,STRPTR String)
{
struct RexxHostBase *RexxHostBase;
SHORT i = 0,j;
LONG Sign;
UBYTE c;
/* Valid argument given? */
if(String)
{
/* Remember sign extension. */
if((Sign = Value) < 0)
Value = -Value;
/* Convert it into ASCII characters (in
* reverse order, i.e. 1234 = "4321").
*/
do
String[i++] = Value % 10 + '0';
while((Value /= 10) > 0);
/* Add sign extension. */
if(Sign < 0)
String[i++] = '-';
/* String NULL-termination. */
String[i] = 0;
/* Reverse the string. */
for(i = 0, j = StrLen((char *)String) - 1 ; i < j ; i++, j--)
{
c = String[i];
String[i] = String[j];
String[j] = c;
}
}
return(String);
}
/* AmigaToUpper(c):
*
* Replacement for toupper() macro, also knows how to
* map international characters to uppercase. Note: not
* a real library module.
*/
STATIC UBYTE
AmigaToUpper(UBYTE c)
{
/* -------- DEC --------- -------- ASCII ------- */
if((c >= 224 && c <= 254) || (c >= 'a' && c <= 'z'))
c -= 32;
return(c);
}
/* RexxStrCmp(Source,Target):
*
* Compares two strings ignoring case.
*/
LONG
RexxStrCmp(STRPTR Source,STRPTR Target)
{
struct RexxHostBase *RexxHostBase;
/* Do the string comparison ignoring case. */
for( ; AmigaToUpper(*Source) == AmigaToUpper(*Target) ; Source++, Target++)
{
if(!(*Source))
return(0);
}
return(AmigaToUpper(*Source) - AmigaToUpper(*Target));
}
/* GetRexxMsg():
*
* Picks up pending RexxMessages from a RexxHost and
* returns them to the caller. I desired, will wait
* for new messages to arrive if none is present yet.
*/
struct RexxMsg *
GetRexxMsg(struct RexxHost *RexxHost,LONG Wait)
{
struct RexxHostBase *RexxHostBase;
struct RexxMsg *RexxMessage = NULL;
/* Valid pointer given? */
if(RexxHost && RexxHost -> rh_SpecialID == 'REXX')
{
/* Try to pick up a message. */
while(!(RexxMessage = (struct RexxMsg *)GetMsg((struct MsgPort *)RexxHost)))
{
/* No message available. Are we to wait? */
if(Wait)
WaitPort((struct MsgPort *)RexxHost);
else
break;
}
}
/* Return the result (may be NULL). */
return(RexxMessage);
}
/* SendRexxMsg():
*
* Sends a single (or a list of) command(s) to Rexx host
* and returns the secondary result.
*/
ULONG
SendRexxMsg(STRPTR HostName,STRPTR *MsgList,STRPTR SingleMsg,LONG GetResult)
{
struct RexxHostBase *RexxHostBase;
struct RexxMsg *RexxMessage;
struct MsgPort *HostPort,*ReplyPort;
ULONG Result = 0;
SHORT i;
/* Valid pointers given? */
if(HostName && (MsgList || SingleMsg))
{
/* Can we find the host? */
if(HostPort = (struct MsgPort *)FindPort((char *)HostName))
{
/* Allocate a reply port. */
if(ReplyPort = (struct MsgPort *)AllocMem(sizeof(struct MsgPort),MEMF_PUBLIC | MEMF_CLEAR))
{
if((ReplyPort -> mp_SigBit = AllocSignal(-1)) != -1)
{
ReplyPort -> mp_Node . ln_Type = NT_MSGPORT;
ReplyPort -> mp_Flags = PA_SIGNAL;
ReplyPort -> mp_SigTask = SysBase -> ThisTask;
InitList(&ReplyPort -> mp_MsgList);
/* Create a Rexx message. */
if(RexxMessage = (struct RexxMsg *)CreateRexxMsg(ReplyPort,"",(char *)HostName))
{
/* A list of arguments or only a single arg? */
if(MsgList)
{
for(i = 0 ; i < 16 ; i++)
RexxMessage -> rm_Args[i] = MsgList[i];
}
else
RexxMessage -> rm_Args[0] = SingleMsg;
/* Do we want result codes? */
if(GetResult)
RexxMessage -> rm_Action = RXFF_RESULT;
/* Send packet and wait for the reply. */
PutMsg(HostPort,RexxMessage);
WaitPort(ReplyPort);
/* Remember result. */
if(GetResult && !RexxMessage -> rm_Result1)
Result = RexxMessage -> rm_Result2;
/* Remove Rexx message. */
DeleteRexxMsg(RexxMessage);
}
/* Free reply port signal bit. */
FreeSignal(ReplyPort -> mp_SigBit);
}
/* Free the replyport itself. */
FreeMem(ReplyPort,sizeof(struct MsgPort));
}
}
}
/* Return the result. */
return(Result);
}
/* GetRexxString():
*
* Copy the result string returned by SendRexxMsg to user
* buffer and/or remove the original string.
*/
VOID
GetRexxString(STRPTR SourceString,STRPTR DestString)
{
struct RexxHostBase *RexxHostBase;
/* Valid pointer given? */
if(SourceString)
{
/* Destination memory buffer given? */
if(DestString)
StrCpy((char *)DestString,(char *)SourceString);
/* Deallocate the original string. */
DeleteArgstring((char *)SourceString);
}
}
/* GetRexxClip():
*
* Searches the rexx clip list for a node with given
* name.
*/
LONG
GetRexxClip(char *Name,LONG WhichArg)
{
struct RexxHostBase *RexxHostBase;
/* Do we have valid buffers and size? */
if(Name && Name[0])
{
struct RexxRsrc *Node;
/* Can we find the clip node? */
if(Node = (struct RexxRsrc *)FindRsrcNode(&RexxSysBase -> rl_ClipList,Name,RRT_CLIP))
{
if(WhichArg)
return(Node -> rr_Arg1);
else
return(Node -> rr_Arg2);
}
}
return(NULL);
}