7 * (C) Copyright 1998 Manuel Lemos.
8 * (C) Copyright 1996-1997 Ian J. Einman.
9 * (C) Copyright 1993-1996 Jaba Development.
10 * (C) Copyright 1993-1996 Jan van den Baard.
11 * All Rights Reserved.
14 * Revision 42.3 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.2 2000/08/08 20:57:26 chodorowski
18 * Minor fixes to build on Amiga.
20 * Revision 42.1 2000/05/15 19:27:00 stegerg
21 * another hundreds of REG() macro replacements in func headers/protos.
23 * Revision 42.0 2000/05/09 22:08:13 mlemos
24 * Bumped to revision 42.0 before handing BGUI to AROS team
26 * Revision 41.11 2000/05/09 20:21:32 mlemos
27 * Bumped to revision 41.11
29 * Revision 41.1 2000/05/09 19:53:44 mlemos
30 * Merged with the branch Manuel_Lemos_fixes.
32 * Revision 1.1.2.1 1998/10/12 01:32:38 mlemos
33 * Initial revision adapted from Ian sources.
40 ** Include necessary headers.
42 #include "include/classdefs.h"
45 ** Object instance data. Every object
46 ** created from this class has this
50 struct MsgPort
*ad_Port
; /* Host message port. */
51 UBYTE
*ad_HostName
; /* Host name. */
52 UBYTE
*ad_FileExt
; /* File extention. */
53 ULONG ad_PendCnt
; /* Messages still un-replied. */
54 REXXCOMMAND
*ad_Commands
; /* Host command list. */
55 struct RDArgs
*ad_DOSParser
; /* ReadArgs() parser. */
62 struct Library
*RexxSysLibraryBase
;
65 #define RexxSysBase ((CD *)cl->cl_UserData)->RexxSysLibraryBase
68 ** Duplicate a string.
70 STATIC UBYTE
*DupStr( AD
*ad
, UBYTE
*str
)
72 UBYTE
*dup
= BGUI_AllocPoolMem( strlen( str
) + 1 );
87 ** Reply a rexx command.
89 STATIC VOID
ReplyRexxCommand(Class
*cl
, struct RexxMsg
*rxm
, LONG prim
, LONG sec
, UBYTE
*res
)
96 if ( rxm
->rm_Action
& RXFF_RESULT
) {
102 ** We setup the secondary result to
103 ** the result string when one was passed.
105 sec
= res
? ( LONG
)CreateArgstring( res
, strlen( res
)) : 0L;
108 ** Primary result bigger than 0?
112 ** Setup the result field
113 ** to point to a string containing
114 ** the secondary result number.
116 sprintf( buf
, "%ld", sec
);
120 ** Negate primary result and
121 ** setup the result field to
122 ** the secondary result.
125 res
= ( UBYTE
* )sec
;
129 ** Setup ARexx it's "RC2" variable to
132 SetRexxVar( rxm
, "RC2", res
, strlen( res
));
135 ** Clear secondary result.
139 } else if ( prim
< 0 )
141 ** Negate primary result.
146 ** Setup result fields.
148 rxm
->rm_Result1
= prim
;
149 rxm
->rm_Result2
= sec
;
152 ** Reply the RexxMsg.
154 ReplyMsg(( struct Message
* )rxm
);
158 ** Free a RexxMsg command.
160 STATIC VOID
FreeRexxCommand(Class
*cl
, struct RexxMsg
*rxm
)
163 ** Delete the result Argstring.
165 if ( ! rxm
->rm_Result1
&& rxm
->rm_Result2
)
166 DeleteArgstring(( UBYTE
* )rxm
->rm_Result2
);
169 ** Close input handle.
171 if ( rxm
->rm_Stdin
&& rxm
->rm_Stdin
!= Input()) {
173 ** If the output handle is the
174 ** same as the input handle we
175 ** can safely clear it.
177 if ( rxm
->rm_Stdout
== rxm
->rm_Stdin
)
178 rxm
->rm_Stdout
= NULL
;
179 Close( rxm
->rm_Stdin
);
180 rxm
->rm_Stdin
= NULL
;
184 ** Close output handle if it is not
185 ** the same as Stdin.
187 if ( rxm
->rm_Stdout
&& rxm
->rm_Stdout
!= Output()) {
188 Close( rxm
->rm_Stdout
);
189 rxm
->rm_Stdout
= NULL
;
193 ** Delete the command Argstring.
195 DeleteArgstring(( UBYTE
* )ARG0( rxm
));
197 ** Delete the message itself.
199 DeleteRexxMsg( rxm
);
203 ** Create a RexxMsg command.
205 STATIC
struct RexxMsg
*CreateRexxCommand(Class
*cl
, AD
*ad
, UBYTE
*comname
, BPTR handle
)
210 ** Create the RexxMsg.
212 if ( rxm
= CreateRexxMsg( ad
->ad_Port
, ad
->ad_FileExt
, ad
->ad_HostName
)) {
214 ** Create the Argstring.
216 if ( rxm
->rm_Args
[ 0 ] = CreateArgstring( comname
, strlen( comname
))) {
218 ** Setup action flags.
220 rxm
->rm_Action
= RXCOMM
| RXFF_RESULT
;
222 ** Setup file handles.
224 rxm
->rm_Stdin
= rxm
->rm_Stdout
= handle
;
228 ** Argstring creation failed.
230 DeleteRexxMsg( rxm
);
236 ** Send a RexxMsg command to the
239 STATIC
struct RexxMsg
*CommandToRexx( AD
*ad
, struct RexxMsg
*rxm
)
244 ** Try to find the "REXX"
249 if ( ! ( rxp
= FindPort( RXSDIR
))) {
251 ** Oops. ARexx server
259 ** Send off the message.
261 PutMsg( rxp
, &rxm
->rm_Node
);
266 ** Increase pending counter.
274 ** Send a command to the ARexx server.
276 STATIC
struct RexxMsg
*SendRexxCommand(Class
*cl
, AD
*ad
, UBYTE
*comname
, BPTR handle
)
281 ** Create a RexxMsg command and
282 ** send it off to the ARexx server.
284 if (rxm
= CreateRexxCommand(cl
, ad
, comname
, handle
))
285 return CommandToRexx(ad
, rxm
);
290 STATIC REXXCOMMAND
*FindRXCommand( AD
*ad
, UBYTE
*comname
, UWORD len
)
292 REXXCOMMAND
*rc
= ad
->ad_Commands
;
294 while ( rc
->rc_Func
) {
295 if ( ! strnicmp( comname
, rc
->rc_Name
, len
) && isspace( comname
[ strlen( rc
->rc_Name
) ] ))
304 ** Execute a command.
306 STATIC VOID
DoRXCommand(Class
*cl
, AD
*ad
, struct RexxMsg
*rxm
)
311 UBYTE
*comname
, *args
, *tmp
, *result
= NULL
;
312 LONG rc
= 20, rc2
= 0;
313 UWORD numargs
= 0, len
= 0;
316 ** Allocate memory for the command
317 ** name and it's argument string.
319 if ( ! ( comname
= ( UBYTE
* )BGUI_AllocPoolMem( strlen(( UBYTE
* )ARG0( rxm
)) + 2 ))) {
320 rc2
= ERROR_NO_FREE_STORE
;
325 ** Copy command name and argument string.
327 strcpy( comname
, ( UBYTE
* )ARG0( rxm
));
330 ** ReadArgs() requires the argument
331 ** string to end with a newline.
333 strcat( comname
, "\n" );
336 ** Find the length of the command
337 ** the start of the arguments.
340 while ( isspace( *args
)) args
++;
342 while ( ! isspace( *args
)) { len
++; args
++; }
347 if ( rco
= FindRXCommand( ad
, tmp
, len
)) {
349 ** Allocate REXXARGS structure.
351 if ( ra
= ( REXXARGS
* )BGUI_AllocPoolMem( sizeof( REXXARGS
))) {
353 ** Count number of expected args.
355 if ( rco
->rc_ArgTemplate
) {
356 tmp
= rco
->rc_ArgTemplate
;
357 while ( *tmp
!= '\n' ) {
358 if ( *tmp
++ == ',' ) numargs
++;
362 ** Allocate arg array.
364 if ( ra
->ra_ArgList
= ( ULONG
* )BGUI_AllocPoolMem( numargs
* sizeof( ULONG
))) {
368 ad
->ad_DOSParser
->RDA_Source
.CS_Buffer
= args
;
369 ad
->ad_DOSParser
->RDA_Source
.CS_Length
= strlen( args
);
370 ad
->ad_DOSParser
->RDA_Source
.CS_CurChr
= 0;
371 ad
->ad_DOSParser
->RDA_DAList
= NULL
;
372 ad
->ad_DOSParser
->RDA_Buffer
= NULL
;
376 if ( ReadArgs( rco
->rc_ArgTemplate
, (LONG
*)ra
->ra_ArgList
, ad
->ad_DOSParser
)) {
378 ** Call the REXX routine.
380 ( rco
->rc_Func
)( ra
, rxm
);
384 result
= ra
->ra_Result
;
386 FreeArgs( ad
->ad_DOSParser
);
391 BGUI_FreePoolMem( ra
->ra_ArgList
);
393 rc2
= ERROR_NO_FREE_STORE
;
398 ( rco
->rc_Func
)( ra
, rxm
);
402 result
= ra
->ra_Result
;
404 BGUI_FreePoolMem( ra
);
406 rc2
= ERROR_NO_FREE_STORE
;
409 ** Not found in our list?
410 ** Maybe it's a script.
412 if ( rm
= CreateRexxCommand(cl
, ad
, ( UBYTE
* )ARG0( rxm
), NULL
)) {
414 ** Save original message.
416 rm
->rm_Args
[ 15 ] = ( STRPTR
)rxm
;
418 ** Let the REXX server see what
419 ** it can do with this.
421 if ( ! CommandToRexx( ad
, rm
))
422 rc2
= ERROR_NOT_IMPLEMENTED
;
424 rc2
= ERROR_NO_FREE_STORE
;
429 ReplyRexxCommand(cl
, rxm
, rc
, rc2
, result
);
433 BGUI_FreePoolMem( comname
);
437 METHOD(ARexxClassNew
, struct opSet
*,ops
)
439 struct TagItem
*attr
= ops
->ops_AttrList
;
442 ULONG rc
, *ecode
, err
, ext
= 1;
443 UBYTE unique_name
[80], *tmp
;
446 * Let the superclass set us up...
448 if (rc
= DoSuperMethodA(cl
, obj
, (Msg
)ops
))
451 * Get the instance data.
453 ad
= INST_DATA(cl
, rc
);
457 * Create a memory pool.
459 if (ad
->ad_MemPool
= LibCreatePool(MEMF_PUBLIC
| MEMF_CLEAR
, 4096, 4096))
464 * host name is supplied.
466 if (ad
->ad_HostName
= (UBYTE
*)GetTagData(AC_HostName
, NULL
, attr
))
471 if (*ad
->ad_HostName
)
474 * Make the name unique.
478 sprintf(unique_name
, "%s.%ld", ad
->ad_HostName
, ext
++);
479 } while ((mp
= FindPort(unique_name
)) && ext
<= 99);
490 if (ad
->ad_HostName
= DupStr(ad
, unique_name
))
495 tmp
= ad
->ad_HostName
;
497 *tmp
= toupper(*tmp
);
503 if (ad
->ad_Port
= CreateMsgPort())
506 * Initialize and add the port.
508 ad
->ad_Port
->mp_Node
.ln_Name
= ad
->ad_HostName
;
509 ad
->ad_Port
->mp_Node
.ln_Pri
= 0;
510 AddPort(ad
->ad_Port
);
511 } else err
= RXERR_OUT_OF_MEMORY
;
512 } else err
= RXERR_OUT_OF_MEMORY
;
513 } else err
= RXERR_PORT_ALREADY_EXISTS
;
514 } else err
= RXERR_NO_PORT_NAME
;
515 } else err
= RXERR_NO_PORT_NAME
;
518 * Do we have a port now?
523 * Find the commandlist.
525 if (ad
->ad_Commands
= (REXXCOMMAND
*)GetTagData(AC_CommandList
, NULL
, attr
))
528 * Setup the AmigaDOS parser.
530 if (ad
->ad_DOSParser
= (struct RDArgs
*)AllocDosObject(DOS_RDARGS
, NULL
))
532 ad
->ad_DOSParser
->RDA_Flags
= RDAF_NOPROMPT
;
534 * Obtain file extention.
536 ad
->ad_FileExt
= (UBYTE
*)GetTagData(AC_FileExtention
, (ULONG
)"rexx", attr
);
540 } else err
= RXERR_OUT_OF_MEMORY
;
541 } else err
= RXERR_NO_COMMAND_LIST
;
544 } else err
= RXERR_OUT_OF_MEMORY
;
547 * See if we got error storage.
549 ecode
= (ULONG
*)GetTagData(AC_ErrorCode
, NULL
, attr
);
550 if (ecode
) *ecode
= err
;
553 * Bliep error...bliep....
555 CoerceMethod(cl
, (Object
*)rc
, OM_DISPOSE
);
562 METHOD(ARexxClassDispose
, Msg
, msg
)
564 AD
*ad
= ( AD
* )INST_DATA( cl
, obj
);
573 * Remove the port from the public list
575 RemPort(ad
->ad_Port
);
577 * Wait for and handle all messages still pending.
579 while (ad
->ad_PendCnt
)
582 * Wait for a message.
584 WaitPort(ad
->ad_Port
);
588 while (rxm
= (struct RexxMsg
*)GetMsg(ad
->ad_Port
))
593 if (rxm
->rm_Node
.mn_Node
.ln_Type
== NT_REPLYMSG
)
596 * Free the message and decrease the
599 FreeRexxCommand(cl
, rxm
);
605 * Tell'm we're getting out of here.
607 ReplyRexxCommand(cl
, rxm
, -20, (LONG
)"Host object closing down", NULL
);
612 * In case there are no messages pending we still
613 * need to reply all that is waiting at the port.
615 while (rxm
= (struct RexxMsg
*)GetMsg(ad
->ad_Port
))
616 ReplyRexxCommand(cl
, rxm
, -20, (LONG
)"Host object closing down", NULL
);
621 DeleteMsgPort(ad
->ad_Port
);
625 * Delete the AmigaDOS parser.
627 if (ad
->ad_DOSParser
)
628 FreeDosObject(DOS_RDARGS
, ad
->ad_DOSParser
);
631 * Delete the port name.
634 BGUI_FreePoolMem(ad
->ad_HostName
);
640 LibDeletePool(ad
->ad_MemPool
);
644 * Let the superclass do the rest.
646 return DoSuperMethodA(cl
, obj
, msg
);
651 METHOD(ARexxClassGet
, struct opGet
*, opg
)
653 AD
*ad
= INST_DATA(cl
, obj
);
657 ** What do they want?
659 switch (opg
->opg_AttrID
)
662 *(opg
->opg_Storage
) = (ULONG
)ad
->ad_HostName
;
665 case AREXX_SignalMask
:
666 *(opg
->opg_Storage
) = (1 << ad
->ad_Port
->mp_SigBit
);
670 rc
= DoSuperMethodA(cl
, obj
, (Msg
)opg
);
678 METHOD(ARexxClassExecute
, struct acmExecute
*, acme
)
680 AD
*ad
= INST_DATA( cl
, obj
);
684 UBYTE
*args
, *tmp
, *result
= NULL
, *com
;
685 UWORD numargs
= 0, len
= 0;
689 ** Allocate a private copy of the command string.
691 if ( com
= ( UBYTE
* )BGUI_AllocPoolMem( strlen( acme
->acme_CommandString
) + 2 )) {
693 ** Make a copy terminated with a newline.
695 strcpy( com
, acme
->acme_CommandString
);
698 ** Find the length of the command
699 ** and the start of the arguments.
702 while ( isspace( *args
)) args
++;
704 while ( ! isspace( *args
)) { len
++; args
++; }
706 ** Look up the command.
708 if ( rco
= FindRXCommand( ad
, tmp
, len
)) {
710 ** Allocate a REXXARGS structure.
712 if ( ra
= ( REXXARGS
* )BGUI_AllocPoolMem( sizeof( REXXARGS
))) {
716 if ( rco
->rc_ArgTemplate
) {
718 ** Count the expected number of arguments.
720 tmp
= rco
->rc_ArgTemplate
;
721 while ( *tmp
!= '\n' ) {
722 if ( *tmp
++ != ',' ) numargs
++;
726 ** Allocate space to parse the args.
728 if ( ra
->ra_ArgList
= ( ULONG
* )BGUI_AllocPoolMem( numargs
* sizeof( ULONG
))) {
732 ad
->ad_DOSParser
->RDA_Source
.CS_Buffer
= args
;
733 ad
->ad_DOSParser
->RDA_Source
.CS_Length
= strlen( args
);
734 ad
->ad_DOSParser
->RDA_Source
.CS_CurChr
= 0;
735 ad
->ad_DOSParser
->RDA_DAList
= NULL
;
736 ad
->ad_DOSParser
->RDA_Buffer
= NULL
;
740 if ( ReadArgs( rco
->rc_ArgTemplate
, (LONG
*)ra
->ra_ArgList
, ad
->ad_DOSParser
)) {
744 ( rco
->rc_Func
)( ra
, NULL
);
750 result
= ra
->ra_Result
;
751 FreeArgs( ad
->ad_DOSParser
);
757 ** Deallocate arg list.
759 BGUI_FreePoolMem( ra
->ra_ArgList
);
761 r2
= ERROR_NO_FREE_STORE
;
766 ( rco
->rc_Func
)( ra
, NULL
);
772 result
= ra
->ra_Result
;
775 ** Deallocate the REXXARGS structure.
777 BGUI_FreePoolMem( ra
);
779 r2
= ERROR_NO_FREE_STORE
;
781 ** When not passed to the rexx server
782 ** we must close the given IO handle
785 if ( acme
->acme_IO
) Close( acme
->acme_IO
);
788 ** We do not send the new-line to
791 com
[ strlen( com
) - 1 ] = '\0';
793 ** Unknown commands are shipped
794 ** off to the REXX server.
796 if ( rxm
= CreateRexxCommand(cl
, ad
, com
, acme
->acme_IO
)) {
797 if ( ! CommandToRexx( ad
, rxm
))
798 r2
= ERROR_NOT_IMPLEMENTED
;
802 r2
= ERROR_NO_FREE_STORE
;
805 ** Deallocate the command copy.
807 BGUI_FreePoolMem( com
);
809 r2
= ERROR_NO_FREE_STORE
;
812 ** Put the results into their
815 if ( acme
->acme_RC
) *( acme
->acme_RC
) = r
;
816 if ( acme
->acme_RC2
) *( acme
->acme_RC2
) = r2
;
817 if ( acme
->acme_Result
) *( acme
->acme_Result
) = result
;
823 /// AREXXM_HANDLE_EVENT
824 METHOD(ARexxClassHandleEvent
, Msg
, msg
)
826 struct RexxMsg
*rxm
, *org
;
827 AD
*ad
= INST_DATA(cl
, obj
);
831 * Get the messages from the port.
833 while (rxm
= (struct RexxMsg
*)GetMsg(ad
->ad_Port
))
838 if ((rxm
->rm_Action
& RXCODEMASK
) != RXCOMM
)
839 ReplyMsg((struct Message
*)rxm
);
840 else if (rxm
->rm_Node
.mn_Node
.ln_Type
== NT_REPLYMSG
)
843 * Reply'd message. See if it was started
846 if (org
= (struct RexxMsg
*)rxm
->rm_Args
[15])
849 ReplyRexxCommand(cl
, org
, 20, ERROR_NOT_IMPLEMENTED
, NULL
);
851 ReplyRexxCommand(cl
, org
, 0, 0, (UBYTE
*)rxm
->rm_Result2
);
854 * Free the message and decrease the pending counter.
856 FreeRexxCommand(cl
, rxm
);
863 DoRXCommand(cl
, ad
, rxm
);
865 ReplyMsg((struct Message
*)rxm
);
873 * Class function table.
875 STATIC DPFUNC ClassFunc
[] = {
876 OM_NEW
, (FUNCPTR
)ARexxClassNew
,
877 OM_DISPOSE
, (FUNCPTR
)ARexxClassDispose
,
878 OM_GET
, (FUNCPTR
)ARexxClassGet
,
879 AREXXM_HANDLE_EVENT
, (FUNCPTR
)ARexxClassHandleEvent
,
880 AREXXM_EXECUTE
, (FUNCPTR
)ARexxClassExecute
,
884 METHOD(ARexxClassMethodNew
, Msg
, msg
)
886 return((ULONG
)((((CD
*)cl
->cl_UserData
)->RexxSysLibraryBase
=OpenLibrary("rexxsyslib.library",36L))!=NULL
));
890 METHOD(ARexxClassMethodDispose
, Msg
, msg
)
892 CD
*class_data
=(CD
*)cl
->cl_UserData
;
894 if(class_data
->RexxSysLibraryBase
)
896 CloseLibrary(class_data
->RexxSysLibraryBase
);
897 class_data
->RexxSysLibraryBase
=NULL
;
904 * Class methods function table.
906 STATIC DPFUNC ClassMethods
[] = {
907 OM_NEW
, (FUNCPTR
)ARexxClassMethodNew
,
908 OM_DISPOSE
, (FUNCPTR
)ARexxClassMethodDispose
,
913 * Initialize the class.
915 makeproto Class
*InitArexxClass(void)
917 return(BGUI_MakeClass(CLASS_DFTable
, ClassFunc
,
918 CLASS_ObjectSize
, sizeof(AD
),
919 CLASS_ClassSize
, sizeof(CD
),
920 CLASS_ClassDFTable
, ClassMethods
,