home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 277.lha / TestRH / src / rderxsupp.asm < prev   
Encoding:
Assembly Source File  |  1989-08-08  |  16.8 KB  |  515 lines

  1. ;*
  2. ;*    RDERXSUPP.ASM
  3. ;*      Reusable routines to provide an asynchronous, recursively callabe
  4. ;*      ARexx ( (C) Bill Hawes) Host.
  5. ;*
  6. ;*      (C) Copyright 1989 by Vidyanath Rao
  7. ;*              All rights reserved.
  8. ;*
  9. ;* These routines may be used in freely redistributable software for
  10. ;* the Amiga (TM of Commodore-Amiga) computer, provided that credit
  11. ;* is given and this notice appears in the software or the documentation.
  12. ;*
  13.  
  14.  
  15.         NOLIST
  16.         INCLUDE "rderexx.i"
  17.         LIST
  18.  
  19.         SECTION RxSuppData,DATA
  20.  
  21. _RHUsrPassWd:
  22.         dc.l 0
  23. _RHMcrPassWd:
  24.         dc.l 0
  25. _RHOutCount:
  26.         dc.w 0
  27. _RMSeqNo:
  28.         dc.w 1
  29.  
  30. rmes3:  dc.b  'Unknown error code: '
  31. rmes4:  dc.b  '        .',0
  32.         CNOP 0,2
  33.  
  34.         XREF     _RexxSysBase,_SysBase,_ArpBase
  35.         XREF    _RHPort,_RHFlags,_ChkPorts,_CmdErr
  36.         XDEF     _RHUsrPassWd,_RHMcrPassWd,_RHOutCount,_RMSeqNo
  37.  
  38. ;_RHPort:       Port used to communicate with ARexx
  39. ;_RHFlags: (UWORD) flags:
  40. ;               bit 0 --> external command being executed
  41. ;                   1 --> execution of this host halted.
  42. ;                   4 --> locked by the user
  43. ;                   5 --> locked by a macro
  44. ;_ChkPorts: (UWORD) flags to indicate invalid signals for msg ports.
  45. ;_CmdErr:       error flags set by the application
  46. ;_RH???PassWd:  Pointer to the pass word set by usr/external macro
  47. ;_RHOutCount:   No of outstanding messages
  48. ;_RMSeqNo:      The serial no of the last msg to Rexx. (modulo 2^16)
  49.  
  50.  
  51.         SECTION RxSuppCode,CODE
  52.  
  53.         far code
  54.         far data
  55.  
  56. ;This is the list of names and function addresses
  57. rhcmds: dc.l    rcn04,_rh_string,rcn05,_rh_msg2usr
  58.         dc.l    rcn06,_rh_lock,rcn07,_rh_unlock
  59.         dc.l    0,0
  60.  
  61.         near code
  62.         near data
  63.  
  64. ;do_command() is the application command dispatcher.
  65. ;drm_end() is called by disprxmsg() to take care of the id
  66.         XREF    _malloc,_do_command,_drm_end,_free
  67.         XDEF    _disprxmsg,_sendrxmsg,_rxerrmsg
  68.         XREF    _rh_string,_rh_msg2usr,_rh_lock,_rh_unlock
  69.  
  70.  
  71. ;This is the list of severity levels and error codes for the flags of
  72. ;_CmdErr.
  73. CErc:   dc.w 20,20,20,20,15,15,15,15
  74.         dc.w 10,10,10,10,10,10,10,10
  75.         dc.w  5,5,5,5,5,5,5,5
  76.         dc.w  5,5,5,5,5,5,5,5
  77.  
  78. msgnm:  dc.b 'RDE RX MESSAGE',0
  79.  
  80. rcn04:  dc.b ((rcn05-rcn04)-2),'STRING',0
  81. rcn05:  dc.b $80|((rcn06-rcn05)-2),'MSGTOUSR',0
  82. rcn06:  dc.b $80|((rcn07-rcn06)-2),'LOCK',0
  83. rcn07:  dc.b $80|((rcn08-rcn07)-2),'UNLOCK',0
  84. rcn08:
  85.  
  86. hastr:  dc.b 'RDE',0
  87. extstr: dc.b 'rde',0
  88. rxnm:   dc.b 'AREXX',0
  89. okstr:  dc.b 'OK',0
  90.  
  91.         CNOP    0,4
  92.  
  93. ;Call the routine as void disprxmsg(struct RexxMsg *);
  94. ;if non-Rexx message, does nothing
  95. ;if our Rexx message, recylces the memory. If a result was returned
  96. ;       it is stored in malloc()'ed storage.
  97. ;At the end a call of the form
  98. ;       drm_end(r2, r1, id)
  99. ;               union {int err; char *result} r2;
  100. ;               long    r1;
  101. ;               void    *id;
  102. ; is made. This lets you decide what to do. The arguments are as follows:
  103. ;       case (r1 = 0, r2 = 0) : No errors, no result string.
  104. ;       case (r1 = 0, r2 != 0): No errors; r2.result points at a copy
  105. ;                                       of the result string. This
  106. ;                                       store must be free()'ed by you.
  107. ;       case (r1>0)           : There was an error. r1 = severity and
  108. ;                                       r2 = error code.
  109. ;       case (r1 = -1)        : The macro went ok, but couldn't malloc()
  110. ;                                       memory for the result string.
  111. ; In all cases, id is the value originally passed to sendrxmsg(),
  112. ;   when the message was sent. [see below].
  113. ;
  114. ;if external Rexx message, and is one of the four listed commands,
  115. ;       the appropriate routine is called.
  116. ;       The calling sequence is rv = <...>(arg, rs, rl);
  117. ;               char *arg = rest of the command string.
  118. ;               long rl, char *rs to be filled in by callee:
  119. ;           The result is:
  120. ;               rv != 0, rl any, rs == NULL :
  121. ;                   There was an error with severity rv and code rl.
  122. ;               rv == 0, rl == 0, rs == NULL :
  123. ;                   No errors and no result string.
  124. ;               rv == 0, rl != 0, rs != NULL :
  125. ;                   No errors, rs points to result string and
  126. ;                       rl = strlen(rs). The storage for rs MUST be
  127. ;                       made with malloc(), as free(rs) call will be made.
  128. ;           NO OTHER COMIBNATIONS ARE ALLOWED. Failure follow this will
  129. ;       cuase memory corruption and a crash.
  130.  
  131. _disprxmsg:
  132.         INITRT  drm,a2/a3/a5,16
  133.         move.l  ARGSTART(sp),a2
  134.         move.l  _RexxSysBase,a6
  135.         move.l  a2,a0
  136.         jsr     _LVOIsRexxMsg(a6); is it a rexx msg?
  137.         tst.l   d0
  138.         beq     drmown ; no check if it is ours
  139.  
  140.         cmp.b   #NT_MESSAGE,LN_TYPE(a2) ; is it external
  141.         beq     drmdoerx ; overkill???
  142.         cmp.b   #NT_REPLYMSG,LN_TYPE(a2) ; is it a reply?
  143.         bne     drmout0 ; funny
  144.         bra     drml05
  145.  
  146. ;The hard part. This is a Rexx message originated by someone else.
  147. ;First check for locks and passwords.
  148. drmdoerx:
  149.         WORDBITS btst,RHB_HALTED,_RHFlags
  150.         beq     drml21
  151.         move.l  #15,d0 ;Host halted
  152.         bra     drmout6
  153.  
  154. drml21: move.l  rm_Args(a2),a3 ; get the command string.
  155.         WORDBITS btst,RHB_USRLOCK,_RHFlags ; check for user lock
  156.         beq     drml22
  157.         move.l  _RHUsrPassWd,a0; check the password
  158.         bra     drml26
  159. drml22: WORDBITS btst,RHB_MCRLOCK,_RHFlags ; and for lock by a macro
  160.         beq     drml32 ; no locks
  161.         move.l  _RHMcrPassWd,a0
  162.         bra     drml26
  163. drml25: cmp.b   (a3)+,d0 ; compare pass words
  164.         bne     drml27 ; permission denied.
  165. drml26: move.b  (a0)+,d0
  166.         bne     drml25
  167.         bra     drml32
  168.  
  169. drml27: move.l  #5,d0 ; locked out by somebody.
  170.         bra     drmout6
  171.  
  172. ;strip initial spaces, and then look for the command.
  173. drml31: addq.l  #1,a3
  174. drml32: cmp.b   #' ',(a3)
  175.         beq     drml31
  176.         move.l  _ArpBase,a6 ;get set
  177.         lea     rhcmds,a5
  178.         bra     drml36
  179. drml35: move.l  #0,d0; length of the command into d0
  180.         move.b  (a0)+,d2 ; now a0 points are the command name
  181.         move.b  d2,d0
  182.         bclr    #7,d0
  183.         move.l  a3,a1 ; and a1 at the (rest of the) command
  184.         jsr     _LVOStrncmp(a6) ; compare, ignoring case
  185.         tst.l   d0
  186.         beq     drml50 ; command found
  187.         addq.l  #4,a5 ;  not this. try next
  188. drml36: move.l  (a5)+,a0
  189.         cmp     #0,a0 ; all done?
  190.         bne     drml35
  191.         move.l  a3,-(sp) ; Yes. So command is not Rexx Host specific.
  192.         WORDBITS bset,RHB_ACTIVE,_RHFlags ; set the active flag
  193.         jsr     _do_command ; call the general dispatcher
  194.         addq.l  #4,sp
  195.         WORDBITS bclr,RHB_ACTIVE,_RHFlags
  196.         move.l  _CmdErr,d0 ; check for errors
  197.         beq     drml40 ; none. go ahead
  198.  
  199.         move.w  #64,d1 ; get the highest bit
  200. drml37: subq.l  #2,d1
  201.         lsr.l   #1,d0 ; shift out a bit
  202.         bne     drml37
  203.         lea     CErc,a1 ; now d1 = error no * 4
  204.         move.w  0(a1,d1.w),d0 ;severity
  205.         ext.l   d0
  206.         bra     drmout6
  207.  
  208. drml40: LONGBITS btst,RXFB_RESULT,rm_Action(a2); is a result string needed
  209.         bne     drml45
  210.         move.l  #0,a0; no just enter 0
  211.         bra     drmout5
  212.  
  213. drml45: lea     okstr,a0;Create and send the default result:
  214.         move.l  #2,d0
  215. drml46: move.l  _RexxSysBase,a6
  216.         jsr     _LVOCreateArgstring(a6)
  217.         tst.l   d0
  218.         bne     drml60 ; result argstring in a0
  219.  
  220. drml47: move.l  #15,d0 ; no memory for argstring
  221.         bra     drmout6
  222.  
  223.  
  224. ;The Rexx Host specific command has been found. The address to call
  225. ;is in 4(a5). a3 points at the command line, past the password.
  226. drml50: btst    #7,d2
  227.         bne     drml51; The called command need not return a result.
  228.         LONGBITS btst,RXFB_RESULT,rm_Action(a2)
  229.         bne     drml51 ; A result is requested
  230.         move.l  #5,d0 ; The called command MUST return a result
  231.         bra     drmout6
  232.  
  233. drml51: bclr    #7,d2
  234.         ext.w   d2
  235.         add.w   d2,a3 ; past the command name
  236.         bra     drml53
  237.  
  238. drml52: addq.l  #1,a3 ; skip past spaces
  239. drml53: cmp.b   #' ',(a3)
  240.         beq     drml52
  241.         move.l  #0,-(sp); push rint,
  242.         move.l  #0,-(sp); rstr and
  243.         move.l  a3,-(sp); arg
  244.         move.l  (a5),a0
  245.         jsr     (a0) ; call the function
  246.         tst.l   d0 ; check for error
  247.         bne     drml55 ; if one, exit
  248.  
  249.         addq.l  #4,sp ; throw away the arg
  250.         move.l  (sp)+,a0 ; keep rs and rl
  251.         move.l  (sp)+,d0; is there a specific result?
  252.         beq     drml40 ; if not, send the default string if one is needed
  253.         move.l  a0,-(sp) ; save the string pointer
  254.         move.l  _RexxSysBase,a6
  255.         jsr     _LVOCreateArgstring(a6)
  256.         move.l  a0,a3 ; save the arg string
  257.         jsr     _free ; free the string
  258.         addq.l  #4,sp ; correct the stack pointer
  259.         cmp     #0,a3 ; check for errors
  260.         beq     drml47 ; no memory for argstring (sphagatti)
  261.         move.l  a3,a0
  262.  
  263. drml60: move.l  #0,d0
  264.         bra     drmout5
  265.  
  266. drml55: lea     12(sp),sp ; throw away the arg and rs
  267. drmout6:
  268.         move.w  #0,a0
  269. ;Enter the result, send the mesage back, clean up and exit.
  270. drmout5:
  271.         move.l  d0,rm_Result1(a2)
  272.         move.l  a0,rm_Result2(a2)
  273.         move.l  _SysBase,a6
  274.         move.l  a2,a1
  275.         jsr     _LVOReplyMsg(a6)
  276.         ENDRT   drm
  277.  
  278.  
  279. drmown: lea     msgnm,a1 ; is it ours? (they are marked with a special
  280.         cmp.l   LN_NAME(a2),a1 ; static string.
  281.         bne     drmnonrx
  282.  
  283. ;This part of the routine handles the case of our message being replied.
  284. drml05: sub.w   #1,_RHOutCount ;correct the count of outstanding messages.
  285.         move.l  rm_Result2(a2),a3;
  286.         move.l  rm_Result1(a2),d0; is there an error indication.
  287.         bne     drmout1 ;there is nothing more to do
  288.         cmp     #0,a3 ; is there a result string?
  289.         beq     drmout1 ; if not, we are done.
  290.         move.l  a3,a0 ; if so store it
  291.         jsr     _LVOLengthArgstring(a6) ; get the length
  292.         move.w  d0,-(sp) ; save the length
  293.         addq.l  #1,d0
  294.         move.l  d0,-(sp) ;allocate memory
  295.         jsr     _malloc
  296.         addq.l  #4,sp
  297.         move.w  (sp)+,d1
  298.         tst.l   d0
  299.         bne     drml15
  300.  
  301.         move.l  #-1,d2 ; if memory failed, set the codes
  302.         bra     drml13 ; and exit
  303.  
  304. drml15: move.l  d0,a0 ; otherwise copy the string
  305.         move.l  a3,a1
  306. drml12: move.b  (a1)+,(a0)+
  307.         dbf     d1,drml12
  308.         move.l  #0,d2
  309.  
  310. drml13: move.l  a3,a0 ; delete the result string
  311.         move.l  d0,a3 ; pointer to copy in a3.
  312.         move.l  _RexxSysBase,a6
  313.         jsr     _LVODeleteArgstring(a6)
  314.         move.l  d2,d0
  315.  
  316. drmout1:
  317.         move.l  60+rm_Args(a2),-(sp) ; push id
  318.         move.l  d0,-(sp) ; and the return code
  319.         move.l  a3,-(sp) ; and the result
  320.  
  321.         move.w  2+rm_Action(a2),d0 ;clear out the arg strings
  322.         and.w   #$0f,d0
  323.         ext.l   d0
  324.         addq.l  #1,d0
  325.         move.l  a2,a0
  326.         jsr     _LVOClearRexxMsg(a6)
  327.         move.l  a2,a0
  328.         jsr     _LVODeleteRexxMsg(a6) ; recycle the memory
  329.  
  330.         jsr     _drm_end ; call the user routine
  331.         lea     12(sp),sp
  332. drmout0:
  333.         ENDRT   drm
  334.  
  335.  
  336. ;The easy (for now) part. Not a Rexx msg. Just throw it back if it was
  337. ;original. Tell the user that something that should not ocur happened.
  338. drmnonrx:
  339.         cmp.b   #NT_MESSAGE,LN_TYPE(a2) ; is it external
  340.         bne     drml90
  341.         move.l  _SysBase,a6
  342.         move.l  a2,a1
  343.         jsr     _LVOReplyMsg(a6) ; if so reply
  344. drml90: ENDRT   drm
  345.  
  346.  
  347. ;This routine handles the chore of creating and sending Rexx messages
  348. ;It is called as
  349. ;       sendrxmsg(act, flgs, args, id)
  350. ;               long act, flgs, id
  351. ;               char *args[];
  352. ;-->Actually, args[i] may either be a string pointer or a long.
  353. ;-->Similarly, id may be a long or void pointer.
  354. ;
  355. ;The roles of these variables are:
  356. ;       act : entered as is into rm_Action field.
  357. ;               act&0x0f will be used as the no of args to be converted.
  358. ;                       must be less than 15, but NOT equal
  359. ;       flgs: this is a bit field with bits 0:14 being the flags for
  360. ;               conversion: bit i is 0 => args[i] is a string
  361. ;                           bit i is 1 => args[i] is a long.
  362. ;               if SRMB_ASYNCH is set, the message is sent asynchornously:
  363. ;                   sendrxmsg will not wait for the message to come back.
  364. ;               if SRMB_HOSTNM is set, the initial Host will ARexx itself.
  365. ;                   usually it is ourselves.
  366. ;       args: This is an array 0..14 of union{long ; char *}. Used to
  367. ;               fill the rexx msg.
  368. ;       id  : This is the message id. Will be entered as is into
  369. ;               rm_Args[15] field of the rexx message.
  370. ;               Is passed as an argument to drm_end.
  371. ;Return value:  0 --> all ok
  372. ;               1 --> too many outstanding messages.
  373. ;               2 --> Unable to create the message/argstrings
  374. ;               3 --> No public REXX port
  375.  
  376. _sendrxmsg:
  377.         INITRT  srm,a2/a3,12
  378.  
  379.         cmp.w   #RDEMAXOUT,_RHOutCount ; if the outstanding count
  380.         bcs     srml01 ; exceeds the max,
  381.  
  382.         move.l  #1,d0 ; error exit
  383.         bra     srmout9
  384.  
  385. srml01: move.l  _RexxSysBase,a6
  386.         move.l  4+ARGSTART(sp),d2 ; flags into d2
  387.         btst    #SRMB_HOSTNM,d2 ; what is the host name
  388.         bne     srml02
  389.         lea     hastr,a0 ; ours
  390.         bra     srml03
  391. srml02: lea     rxnm+1,a0 ;
  392. srml03: move.l  a0,d0
  393.         lea     extstr,a1
  394.         move.l  _RHPort,a0 ; set the reply port
  395.         jsr     _LVOCreateRexxMsg(a6)
  396.         tst.l   d0 ; success?
  397.         bne     srml05
  398.  
  399. srmerr1:
  400.         move.l  #2,d0 ; no, set error code
  401.         bra     srmout9 ;and exit
  402.  
  403. srml05: move.l  a0,a2 ; save the mesage pointer
  404.         move.l  ARGSTART(sp),d0
  405.         WORDBITS btst,RHB_NOIO,_RHFlags ; i/o allowed?
  406.         beq     srml07
  407.         bset    #RXFB_NOIO,d0
  408. srml07: move.l  d0,rm_Action(a2) ; set the Action field.
  409.         move.l  12+ARGSTART(sp),60+rm_Args(a2) ; and the id
  410.         lea     msgnm,a1 ;mark the name field
  411.         move.l  a1,LN_NAME(a2)
  412.         and.w   #$0f,d0 ; find the no of args
  413.         move.w  d0,d1
  414.         add.w   #1,d0
  415.         lea     rm_Args(a2),a1
  416.         move.l  8+ARGSTART(sp),a0 ; arg array passed
  417. srml06: move.l  (a0)+,(a1)+ ; copy the arg array
  418.         dbf     d1,srml06
  419.         ext.l   d0 ; convert the array
  420.         move.l  #0,d1 ; the lower half of the flags into d1
  421.         move.w  d2,d1 ; into d1
  422.         move.l  a2,a0 ; and msg ptr into a0
  423.         jsr     _LVOFillRexxMsg(a6)
  424.         tst.l   d0
  425.         beq     srmerr2
  426.  
  427. srml10: move.l  _SysBase,a6 ; now find the rexx port
  428.         jsr     _LVOForbid(a6) ; disable task switching while we put
  429.         lea     rxnm+1,a1 ; the msg
  430.         btst    #SRMB_TONAME,d2
  431.         beq     srml11
  432.         subq.l  #1,a1
  433. srml11: jsr     _LVOFindPort(a6)
  434.         tst.l   d0
  435.         beq     srmerr3
  436.         move.l  d0,a0 ; send the message
  437.         move.l  a2,a1
  438.         jsr     _LVOPutMsg(a6)
  439.         jsr     _LVOPermit(a6)
  440.         add.w   #1,_RHOutCount ; bump the out count
  441.         add.w   #1,_RMSeqNo ; and the sequence
  442.         btst    #SRMB_ASYNCH,d2 ; is this asynch
  443.         bne     srml35
  444.  
  445.         subq.l  #4,sp ; create an empty slot on the stack
  446. srml20: move.l  _RHPort,a0
  447.         jsr     _LVOWaitPort(a6) ; wait for a msg
  448.         bra     srml26
  449. srml25: move.l  d0,(sp) ; take care of the message
  450.         move.l  d0,a3
  451.         jsr     _disprxmsg
  452.         cmp.l   a2,a3 ; is the msg we just sent?
  453.         beq     srml30 ; yes quit
  454.         move.l  _SysBase,a6
  455. srml26: move.l  _RHPort,a0
  456.         jsr     _LVOGetMsg(a6) ; get the next message
  457.         tst.l   d0
  458.         bne     srml25 ; and loop
  459.         beq     srml20 ; we are not done till we got the msg we sent
  460.  
  461. srml30: addq.l  #4,sp ; correct the stack
  462.         WORDBITS bset,CPB_RHPORT,_ChkPorts
  463.  
  464. srml35: move.l  #0,d0
  465. srmout9:
  466.         ENDRT   srm
  467.  
  468. srmerr3:        ; no REXX port. clear and delete the rexx msg
  469.         jsr     _LVOPermit(a6)
  470.         move.l  _RexxSysBase,a6
  471.         move.w  2+ARGSTART(sp),d0 ; find the no of args
  472.         and.w   #$0f,d0
  473.         add.w   #1,d0
  474.         ext.l   d0
  475.         move.l  a2,a0
  476.         jsr     _LVOClearRexxMsg(a6)
  477.         move.l  #3,d2
  478.         bra     srml50
  479.  
  480. srmerr2:
  481.         move.l  #2,d2
  482. srml50: move.l  a2,a0
  483.         jsr     _LVODeleteRexxMsg(a6)
  484.         move.l  d2,d0
  485.         ENDRT   srm
  486.  
  487.  
  488. ;
  489. ;This routine is called as rxerrmsg(ec)
  490. ;       where long ec is the error code, the result2 from ARexx
  491.  
  492. _rxerrmsg:
  493.         move.l  4(sp),d0; get the error code
  494.         move.l  _RexxSysBase,a6
  495.         jsr     _LVOErrorMsg(a6) ; convert to message
  496.         tst.l   d0 ; known error code?
  497.         beq     reml05
  498.         addq.l  #8,a0 ; add the NexxStr offset
  499.         bra     reml10
  500.  
  501. reml05: lea     4+rmes4,a0 ; unknown error code
  502.         move.l  #$20202020,d0 ; blank out the space for
  503.         move.l  d0,(a0) ; the error code
  504.         move.l  d0,-(a0)
  505.         move.l  4(sp),d0 ; convert error code to ascii
  506.         move.l  #8,d1 ; and put into the string.
  507.         jsr     _LVOCVi2a(a6)
  508.         lea     rmes3,a0
  509.  
  510. reml10: move.l  a0,d0 ; pointer to the error string
  511.         rts
  512.  
  513.  
  514. END
  515.