/* ** rexxhost.library - ARexx host management support library ** ** Copyright © 1990-1992 by Olaf `Olsen' Barthel ** All Rights Reserved */ /* CreateRexxHost(HostName): * * Creates a RexxHost (special MsgPort) with a given name. * Returns NULL if port already exists. */ struct RexxHost * __saveds __asm CreateRexxHost(register __a0 STRPTR HostName) { struct RexxHost *RexxHost; /* Valid name given? */ if(HostName) { if(HostName[0]) { /* Already present? */ if(!FindPort(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 = (UBYTE *)AllocMem(strlen(HostName) + 1,MEMF_PUBLIC)) { /* Copy the name. */ strcpy(RexxHost -> rh_Port . mp_Node . ln_Name,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 * __saveds __asm DeleteRexxHost(register __a0 struct RexxHost *RexxHost) { /* Valid host port given? */ if(RexxHost) { if(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 __saveds __asm SendRexxCommand(register __a0 struct RexxHost *HostPort,register __a1 STRPTR CommandString,register __a2 STRPTR FileExtension,register __a3 STRPTR HostName) { struct MsgPort *RexxPort = (struct MsgPort *)FindPort(RXSDIR); struct RexxMsg *HostMessage; /* Valid pointers given? */ if(CommandString && HostPort && RexxPort) { if(HostPort -> rh_SpecialID == 'REXX') { /* 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,FileExtension,HostName)) { /* Add the command. */ if(HostMessage -> rm_Args[0] = CreateArgstring(CommandString,strlen(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 __saveds __asm FreeRexxCommand(register __a0 struct RexxMsg *RexxMessage) { /* Valid pointer given? */ if(RexxMessage) { if(RexxMessage -> rm_Node . mn_Node . ln_Type == NT_REPLYMSG) { /* Remove argument. */ if(RexxMessage -> rm_Args[0]) DeleteArgstring(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 __saveds __asm ReplyRexxCommand(register __a0 struct RexxMsg *RexxMessage,register __d0 LONG Primary,register __d1 LONG Secondary,register __a1 STRPTR Result) { /* Valid pointer given? */ if(RexxMessage) { if(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(Result,strlen(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 __saveds __asm GetRexxCommand(register __a0 struct RexxMsg *RexxMessage) { if(RexxMessage) { if(RexxMessage -> rm_Node . mn_Node . ln_Type != NT_REPLYMSG) return(RexxMessage -> rm_Args[0]); } return(NULL); } /* GetRexxArg(RexxMessage): * * Returns a pointer to the first RexxMsg argument. */ STRPTR __saveds __asm GetRexxArg(register __a0 struct RexxMsg *RexxMessage) { if(!RexxMessage) return(NULL); else return(RexxMessage -> rm_Args[0]); } /* GetRexxResult1(RexxMessage): * * Returns the 1st RexxMsg result. */ LONG __saveds __asm GetRexxResult1(register __a0 struct RexxMsg *RexxMessage) { if(!RexxMessage) return(NULL); else return(RexxMessage -> rm_Result1); } /* GetRexxResult2(RexxMessage): * * Returns the 2nd RexxMsg result. */ LONG __saveds __asm GetRexxResult2(register __a0 struct RexxMsg *RexxMessage) { 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 __regargs 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 __saveds __asm GetToken(register __a0 STRPTR String,register __a1 LONG *StartChar,register __a2 STRPTR AuxBuff,register __d0 LONG MaxLength) { LONG i,StrEnd = 0,MaxPos = strlen(String); /* Last counter position. */ if(MaxPos >= MaxLength + *StartChar) MaxPos = MaxLength + *StartChar - 1; /* Already finished with argument string? */ if(*StartChar <= strlen(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(AuxBuff,(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 __saveds __asm GetStringValue(register __a0 STRPTR String) { LONG Value,i; BYTE Sign = 1; /* Valid argument given? */ if(String) { if(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 __saveds __asm BuildValueString(register __d0 LONG Value,register __a0 STRPTR String) { LONG Sign,i = 0,j; 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(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 __regargs 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 __saveds __asm RexxStrCmp(register __a0 STRPTR Source,register __a1 STRPTR Target) { /* 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 * __saveds __asm GetRexxMsg(register __a0 struct RexxHost *RexxHost,register __d0 LONG Wait) { struct RexxMsg *RexxMessage = NULL; /* Valid pointer given? */ if(RexxHost) { if(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 __saveds __asm SendRexxMsg(register __a0 STRPTR HostName,register __a1 STRPTR *MsgList,register __a2 STRPTR SingleMsg,register __d0 LONG GetResult) { 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(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; NewList(&ReplyPort -> mp_MsgList); /* Create a Rexx message. */ if(RexxMessage = (struct RexxMsg *)CreateRexxMsg(ReplyPort,"",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 __saveds __asm GetRexxString(register __d0 STRPTR SourceString,register __d1 STRPTR DestString) { /* Valid pointer given? */ if(SourceString) { /* Destination memory buffer given? */ if(DestString) strcpy(DestString,SourceString); /* Deallocate the original string. */ DeleteArgstring(SourceString); } } /* GetRexxClip(): * * Searches the rexx clip list for a node with given * name. */ LONG __saveds __asm GetRexxClip(register __a0 UBYTE *Name,register __d0 LONG WhichArg) { /* Do we have valid buffers and size? */ if(Name) { if(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); }