home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 2: PC
/
frozenfish_august_1995.bin
/
bbs
/
d03xx
/
d0355.lha
/
RexxHostLib
/
RexxHostLib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-12
|
12KB
|
556 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 .: 12
*
* Date Author Comment
* ========= ======== ====================
* 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 12
/* The protos. */
struct RexxMsg *CreateRexxMsg(struct MsgPort *,char *,char *);
STRPTR CreateArgstring(char *,LONG);
VOID DeleteRexxMsg(struct RexxMsg *);
VOID DeleteArgstring(char *);
STATIC LONG AmigaToUpper(LONG);
/* The magic pragma. */
#pragma regcall(AmigaToUpper(d0))
/* Bill Hawes didn't distribute an .fd file along
* with the 1.10 release of ARexx. I had to put these
* pragmas together by hand.
*/
#pragma amicall(RexxSysBase, 0x90, CreateRexxMsg(a0,a1,d0))
#pragma amicall(RexxSysBase, 0x7e, CreateArgstring(a0,d0))
#pragma amicall(RexxSysBase, 0x96, DeleteRexxMsg(a0))
#pragma amicall(RexxSysBase, 0x84, DeleteArgstring(a0))
/* 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 = NULL;
/* Our pointer to ExecBase. */
extern struct ExecBase *SysBase;
if(HostName && HostName[0])
{
/* Already present? */
if(!FindPort((char *)HostName))
{
LONG SigBit;
/* Allocate a signal bit. */
if((SigBit = AllocSignal(-1)) == -1)
goto Quit;
/* Allocate the port body. */
if(!(RexxHost = (struct RexxHost *)AllocMem(sizeof(struct RexxHost),MEMF_PUBLIC | MEMF_CLEAR)))
{
FreeSignal(SigBit);
goto Quit;
}
/* 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)))
{
FreeMem(RexxHost,sizeof(struct RexxHost));
FreeSignal(SigBit);
RexxHost = NULL;
goto Quit;
}
/* 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_SigBit = SigBit;
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);
}
}
Quit: return(RexxHost);
}
/* 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;
if(RexxHost && RexxHost -> rh_SpecialID == 'REXX')
{
/* Remove it from the public list. */
RemPort(&RexxHost -> rh_Port);
/* Make it difficult to reuse it by accident. */
RexxHost -> rh_Port . mp_Node . ln_Type = 0xFF;
RexxHost -> rh_Port . mp_MsgList . lh_Head = (struct Node *)-1;
/* 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)
return(FALSE);
/* 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)))
return(FALSE);
/* Add the command. */
if(!(HostMessage -> rm_Args[0] = CreateArgstring((char *)CommandString,StrLen((char *)CommandString))))
{
DeleteRexxMsg(HostMessage);
return(FALSE);
}
/* This is a command, not a function. */
HostMessage -> rm_Action = RXCOMM;
/* Release it... */
PutMsg(RexxPort,HostMessage);
/* Successful action. */
return(TRUE);
}
/* 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);
}
/* 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;
LONG i,StrEnd = 0,MaxPos = StrLen((char *)String);
/* Last counter position. */
if(MaxPos >= MaxLength)
MaxPos = MaxLength - 1;
/* Already finished with argument string? */
if(*StartChar > StrLen((char *)String) - 1 || !String || !String[0] || !AuxBuff || !MaxLength)
return(NULL);
/* Parse the argument string... */
for(i = *StartChar ; i <= MaxPos ; i++)
{
/* Skip leading blanks... */
if(!StrEnd && String[i] == ' ')
{
while(String[i] == ' ' && i < MaxPos)
{
i++;
(*StartChar)++;
}
}
/* Found an argument. */
if(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 i,Value,Sign = 1;
/* Valid argument given? */
if(!String || !String[0])
return(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);
}
/* 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;
LONG i = 0,j,c,Sign;
/* Valid argument given? */
if(!String)
return(NULL);
/* 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;
}
/* Finished, return the string. */
return(String);
}
/* AmigaToUpper(c):
*
* Replacement for toupper() macro, also knows how to
* map international characters to uppercase. Note: not
* a real library module.
*/
STATIC LONG
AmigaToUpper(LONG 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));
}