6 #include <exec/types.h>
7 #include <utility/tagitem.h>
8 #include <proto/exec.h>
9 #include <proto/intuition.h>
10 #include <proto/rexxsyslib.h>
11 #include <proto/utility.h>
13 #include <rexx/rxslib.h>
14 #include <rexx/errors.h>
15 //#include "rexxmsgext.h" // this should change depening on the ultimate location of the structures
20 * Structure for the rexx host. Most of the code is inspired from Olaf
21 * Barthel's sample ARexx code from the developer CD 2.1
33 struct RexxMsg *rexxMsg;
35 struct RexxHost *rexxHost;
38 STRPTR dupstr(STRPTR src)
45 if((dest = IExec->AllocVec(len + 1, MEMF_ANY)))
57 struct MsgPort *port = IExec->AllocSysObjectTags(ASOT_PORT, TAG_END);
63 struct TimeRequest *req = IExec->AllocSysObjectTags(ASOT_IOREQUEST,
64 ASOIOR_Size, sizeof(struct TimeRequest),
65 ASOIOR_ReplyPort, port,
70 IExec->FreeSysObject(ASOT_PORT, port);
74 int8 deverr = IExec->OpenDevice("timer.device", UNIT_MICROHZ,
77 if (deverr != IOERR_SUCCESS)
79 IExec->FreeSysObject(ASOT_IOREQUEST, req);
80 IExec->FreeSysObject(ASOT_PORT, port);
89 CloseTimer(struct TimeRequest *req)
93 struct MsgPort *port = req->Request.io_Message.mn_ReplyPort;
95 IExec->CloseDevice(&req->Request);
96 IExec->FreeSysObject(ASOT_IOREQUEST, req);
97 IExec->FreeSysObject(ASOT_PORT, port);
102 ReturnRexxMsg(struct RexxMsg * Message, CONST_STRPTR Result)
104 STRPTR ResultString = NULL;
106 /* No error has occured yet. */
109 /* Set up the RexxMsg to return no error. */
110 Message->rm_Result1 = RC_OK;
111 Message->rm_Result2 = 0;
113 /* Check if the command should return a result. */
114 if((Message->rm_Action & RXFF_RESULT) && Result != NULL)
116 /* To return the result string we need to make
117 * a copy for ARexx to use.
119 if((ResultString = IRexxSys->CreateArgstring(Result, strlen(Result))))
121 /* Put the string into the secondary
124 Message->rm_Result2 = (LONG)ResultString;
128 /* No memory available. */
129 ErrorCode = ERR10_003;
133 /* Reply the message, regardless of the error code. */
134 IExec->ReplyMsg((struct Message *)Message);
141 ReturnErrorMsg(struct RexxMsg *msg, CONST_STRPTR port, int32 rc, int32 rc2)
143 /* To signal an error the rc_Result1
144 * entry of the RexxMsg needs to be set to
145 * RC_ERROR. Unfortunately, we cannot convey
146 * the more meaningful error code through
147 * this interface which is why we set a
148 * Rexx variable to the error number. The
149 * Rexx script can then take a look at this
150 * variable and decide which further steps
153 msg->rm_Result1 = rc;
154 msg->rm_Result2 = rc2;
156 /* Turn the error number into a string as
157 * ARexx only deals with strings.
160 IUtility->SNPrintf(value, sizeof(value), "%ld", rc2);
162 /* Build the name of the variable to set to
163 * the error number. We will use the name of
164 * the host name and append ".LASTERROR".
166 IRexxSys->SetRexxVarFromMsg("RC2", value, msg);
168 IExec->ReplyMsg(&msg->rm_Node);
172 PutMsgTo(CONST_STRPTR name, struct Message *msg)
178 struct MsgPort *port = IExec->FindPort(name);
181 IExec->PutMsg(port, msg);
191 STRPTR DoRexx(STRPTR port, STRPTR command, int32 *rc, int32 *rc2)
195 STRPTR result = NULL;
198 struct MsgPort *replyPort = IExec->AllocSysObjectTags(ASOT_PORT, TAG_END);
199 if (replyPort == NULL)
204 struct RexxMsg *rexxMsg = IRexxSys->CreateRexxMsg(replyPort, NULL, NULL);
205 ((struct Node *)rexxMsg)->ln_Name = "REXX";
208 IExec->FreeSysObject(ASOT_PORT, replyPort);
214 rexxMsg->rm_Args[0] = IRexxSys->CreateArgstring(command, strlen(command));
216 if (rexxMsg->rm_Args[0] != NULL)
218 rexxMsg->rm_Action = RXCOMM | RXFF_RESULT | RXFF_STRING;
220 sent = PutMsgTo(port, (struct Message*)rexxMsg);
224 IExec->WaitPort(replyPort);
225 (void)IExec->GetMsg(replyPort);
232 *rc = rexxMsg->rm_Result1;
236 if (rexxMsg->rm_Result2 != 0)
238 result = (STRPTR)rexxMsg->rm_Result2;
243 *rc2 = rexxMsg->rm_Result2;
246 IRexxSys->DeleteArgstring(rexxMsg->rm_Args[0]);
247 rexxMsg->rm_Args[0] = NULL;
250 IRexxSys->DeleteRexxMsg(rexxMsg);
253 IExec->FreeSysObject(ASOT_PORT, replyPort);
258 dup = dupstr(result);
260 IRexxSys->DeleteArgstring(result);
268 struct RexxHost *CreateRexxHost(CONST_STRPTR PortName)
270 struct RexxHost *newHost = IExec->AllocVecTags(sizeof(struct RexxHost),
271 AVT_Type, MEMF_PRIVATE, AVT_ClearWithValue, 0, TAG_DONE);
278 IUtility->Strlcpy(newHost->PortName, PortName, sizeof(newHost->PortName));
282 /* Check if the name already exists */
283 if (IExec->FindPort(PortName) != NULL)
288 IUtility->SNPrintf(newHost->PortName, sizeof(newHost->PortName), "%s.%ld", PortName, index);
291 if (IExec->FindPort(newHost->PortName) == NULL)
298 newHost->Port = IExec->AllocSysObjectTags(ASOT_PORT,
299 ASOPORT_Name, newHost->PortName,
300 ASOPORT_Public, TRUE,
305 if (newHost->Port == NULL)
307 IExec->FreeVec(newHost);
315 void DeleteRexxHost(struct RexxHost *host)
324 while ((msg = (struct RexxMsg *)IExec->GetMsg(host->Port)) != NULL)
326 msg->rm_Result1 = RC_FATAL;
327 IExec->ReplyMsg((struct Message *)msg);
330 IExec->FreeSysObject(ASOT_PORT, host->Port);
334 IExec->FreeVec(host);
338 void WaitRexxHost(struct RexxHost *rexxHost, int timeout)
341 struct TimeRequest *req = NULL;
342 uint32 timermask = 0;
350 timermask = 1L << req->Request.io_Message.mn_ReplyPort->mp_SigBit;
352 req->Request.io_Command = TR_ADDREQUEST;
353 req->Time.Seconds = 0;
354 req->Time.Microseconds = timeout;
356 IExec->SendIO(&req->Request);
360 uint32 hostmask = 1L << rexxHost->Port->mp_SigBit;
361 uint32 waitmask = timermask | hostmask | SIGBREAKF_CTRL_C;
363 uint32 sigmask = IExec->Wait(waitmask);
367 IExec->AbortIO(&req->Request);
368 IExec->WaitIO(&req->Request);
372 if (sigmask & SIGBREAKF_CTRL_C)
380 struct ARexxMsg *GetMsgRexxHost(struct RexxHost *rexxHost)
382 struct ARexxMsg *am = NULL;
384 struct RexxMsg *rexxMsg = NULL;
386 rexxMsg = (struct RexxMsg *)IExec->GetMsg(rexxHost->Port);
389 if((am = IExec->AllocVecTags(sizeof(struct ARexxMsg),AVT_Type, MEMF_PRIVATE, AVT_ClearWithValue, 0, TAG_DONE)))
391 am->rexxMsg = rexxMsg;
392 am->rexxHost = rexxHost;
393 am->isReplied = FALSE;
400 uint32 GetSignalRexxHost(struct RexxHost *rexxHost)
402 return rexxHost->Port->mp_SigBit;
406 void ReplyARexxMsg(struct ARexxMsg *am, int rc, int rc2, STRPTR result)
414 ReturnRexxMsg(am->rexxMsg, result);
418 ReturnErrorMsg(am->rexxMsg, am->rexxHost->PortName,rc,rc2);
420 am->isReplied = TRUE;
425 STRPTR GetVarARexxMsg(struct ARexxMsg *am, STRPTR varname)
427 STRPTR result = IExec->AllocVecTags(256,AVT_Type, MEMF_PRIVATE, AVT_ClearWithValue, 0, TAG_DONE);
430 IRexxSys->GetRexxVarFromMsg(varname, result, am->rexxMsg);
435 void SetVarARexxMsg(struct ARexxMsg *am, STRPTR varname, STRPTR value)
437 IRexxSys->SetRexxVarFromMsg(varname, value, am->rexxMsg);
440 void DeleteARexxMsg(struct ARexxMsg *am)
444 IExec->ReplyMsg(&am->rexxMsg->rm_Node);
445 am->isReplied = TRUE;
450 STRPTR GetArgsARexxMsg(struct ARexxMsg *am)
452 return am->rexxMsg->rm_Args[0];
455 MODULE = Amiga::ARexx PACKAGE = Amiga::ARexx
463 RETVAL = CreateRexxHost(name);
467 void Host_delete(rexxhost)
470 DeleteRexxHost(rexxhost);
472 void Host_wait(rexxhost,timeout)
476 WaitRexxHost(rexxhost,timeout);
478 uint32 Host_signal(rexxhost)
481 RETVAL = GetSignalRexxHost(rexxhost);
485 APTR Host_getmsg(rexxhost)
488 RETVAL = GetMsgRexxHost(rexxhost);
492 void Msg_reply(rexxmsg,rc,rc2,result)
498 ReplyARexxMsg(rexxmsg,rc,rc2,result);
500 void Msg_delete(rexxmsg)
503 DeleteARexxMsg(rexxmsg);
505 STRPTR Msg_argstr(rexxmsg)
508 RETVAL = GetArgsARexxMsg(rexxmsg);
512 STRPTR Msg_getvar(rexxmsg,varname)
516 RETVAL = GetVarARexxMsg(rexxmsg,varname);
517 sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
518 if (RETVAL) IExec->FreeVec(RETVAL);
520 void Msg_setvar(rexxmsg,varname,value)
525 SetVarARexxMsg(rexxmsg,varname,value);
527 STRPTR _DoRexx(port,command,rc,rc2)
533 RETVAL = DoRexx(port,command,&rc,&rc2);
534 sv_setiv(ST(2), (IV)rc);
536 sv_setiv(ST(3), (IV)rc2);
538 sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
539 IExec->FreeVec(RETVAL);