home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / jËzyki_programowania / amigae / e_v3.2a / pdsrc / arexxport.e < prev    next >
Text File  |  2001-03-31  |  10KB  |  368 lines

  1. /* FOLD info
  2.         ~~~~ */
  3.  
  4. /* ARexxPort.e 1.0 - by Leon Woestenberg (leon@stack.urc.tue.nl) */
  5. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  6. /*
  7.  
  8.    Here I present some basic functions to make your E programs
  9.    capable of communicating with other multitasking programs via
  10.    ARexx. With these functions your program can:
  11.  
  12.    · Receive and react to ARexx commands that are sent to it.
  13.    · Invoke Rexx Master to run commands that your program does not
  14.      understand. This can be an ARexx script (in REXX:) too.
  15.    · Send ARexx commands to other programs or to Rexx Master.
  16.  
  17.    This source is public domain, so use it :)
  18.  
  19.    The source is fully commented and is almost self explaining. The
  20.    only hard thing is this: When an incoming ARexx message contains
  21.    a command that is not supported by your program, this message
  22.    is NOT YET REPLIED. First, a NEW message is created that is sent
  23.    to Rexx Master. This new message contains a pointer to the first
  24.    message. Now, when the new message is replied by Rexx Master, we
  25.    can remove the first message from memory (by using the pointer).
  26.    In this way, ARexx scripts can transparantly be used with ARexx
  27.    commands. Note that the default extension for these script can
  28.    be adapted for your program in the sendRexxMsg procedure.
  29.  
  30.    ARexx adds a really nice capability to your multitasking Amiga,
  31.    as tasks can interact in realtime with each other, so that they
  32.    can use each others features. Think about how your programs can
  33.    be extended with a nice ARexx interface.
  34.  
  35.    If you have any questions, suggestions or even bugreports, reach
  36.    me via Internet email. More common questions/discussions about
  37.    this source are also welcome on the Amiga E mailing list.
  38.  
  39.                               Leon Woestenberg (leon@stack.urc.tue.nl)
  40.  
  41. */
  42. /* FEND */
  43. /* FOLD "modules" */
  44.  
  45. MODULE 'exec/ports','exec/nodes'
  46. MODULE 'rexxsyslib','rexx/rexxio','rexx/rxslib','rexx/errors','rexx/storage'
  47. MODULE 'dos/dos'
  48.  
  49. /* FEND */
  50. /* FOLD "definitions" */
  51.  
  52. DEF hostport=NIL:PTR TO mp
  53. DEF runflag=TRUE
  54. DEF unconfirmed=0
  55.  
  56. /* FEND */
  57.  
  58. /* FOLD "main" */
  59. PROC main() HANDLE
  60.  
  61.   /* open rexx library */
  62.   IF (rexxsysbase:=OpenLibrary('rexxsyslib.library',0))
  63.  
  64.     /* create a host port for arexx */
  65.     IF (hostport:=createPort('ExampleHost',0))
  66.  
  67.     /* examples of your program sending arexx commands to others
  68.        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  69.  
  70.     /*
  71.     
  72.     /* tell GoldED to move cursor up one line */
  73.     sendRexxMsg('GOLDED.1','UP',NIL,0)
  74.  
  75.     /* tell the command shell to execute the list command */
  76.     sendRexxMsg('REXX','"ADDRESS COMMAND list"',NIL,0)
  77.  
  78.     /* run a script from REXX: (set the default extension in sendRexxMsg) */
  79.     sendRexxMsg('REXX','scriptname',NIL,0)
  80.  
  81.     /* send a 'QUIT' command to ourselves :o) */
  82.     sendRexxMsg('ExampleHost','QUIT',NIL,0)
  83.  
  84.     */
  85.  
  86.     /* inform the user we are running */
  87.     WriteF('Waiting for events to occur. Send me an ARexx QUIT command by typing:\nrx "ADDRESS \aExampleHost\a; QUIT" from a shell. Or press CTRL-C to break me.\n')
  88.     
  89.     /* wait for events */
  90.     wait()
  91.  
  92.     deletePort(hostport)
  93.     ELSE
  94.       WriteF('Sorry dude, seems like I\am already running once.\n')
  95.     ENDIF
  96.     CloseLibrary(rexxsysbase)
  97.   ELSE
  98.     WriteF('Could not open the rexxsyslib.library. I really need it!\n')
  99.   ENDIF
  100. EXCEPT
  101.   WriteF('Something like \d went wrong, ya see?\n')
  102.   deletePort(hostport)
  103.   hostport:=NIL
  104.   IF rexxsysbase
  105.     CloseLibrary(rexxsysbase)
  106.     rexxsysbase:=NIL
  107.   ENDIF
  108. ENDPROC
  109. /* FEND */
  110. /* FOLD "wait" */
  111. PROC wait()
  112.  
  113.   DEF signalmask=0
  114.   DEF hostmask=0
  115.  
  116.   /* signalmask for our host port */
  117.   hostmask:=Shl(1,hostport.sigbit)
  118.  
  119.   /* still running or unconfirmed messages? */
  120.   WHILE runflag OR unconfirmed
  121.  
  122.     /* wait for event signals */
  123.     signalmask:=Wait(hostmask OR SIGBREAKF_CTRL_C)
  124.  
  125.     /* and handle all happened events */
  126.     IF signalmask AND hostmask THEN handleRexxMsg()
  127.     IF signalmask AND SIGBREAKF_CTRL_C THEN runflag:=FALSE
  128.  
  129.   ENDWHILE
  130. ENDPROC
  131. /* FEND */
  132.  
  133. /* FOLD "handleRexxMsg" */
  134. PROC handleRexxMsg()
  135.  
  136.   /* pointer to handled message */
  137.   DEF rexxmsg:PTR TO rexxmsg
  138.   /* pointer to messagenode */
  139.   DEF msgnode:PTR TO mn
  140.   /* pointer to listnode of message */
  141.   DEF listnode:PTR TO ln
  142.  
  143.   /* list of 16 pointers to command strings  */
  144.   DEF rexxargs:PTR TO LONG
  145.  
  146.   /* points to first char of trimmed command */
  147.   DEF command:PTR TO CHAR
  148.   
  149.   /* (another) message in queue? */
  150.   WHILE rexxmsg:=GetMsg(hostport)
  151.  
  152.     /* set pointer to messagenode */
  153.     msgnode:=rexxmsg.mn
  154.  
  155.     /* set pointer to listnode */
  156.     listnode:=msgnode.ln
  157.  
  158.     /* set pointer to commands */
  159.     rexxargs:=rexxmsg.args
  160.  
  161.     /* confirmation reply of a message sent by us? */
  162.     IF listnode.type=NT_REPLYMSG
  163.  
  164.       /* original message pointer present? */
  165.       IF rexxargs[15]
  166.         /* reply original message */
  167.         ReplyMsg(rexxargs[15])
  168.       ENDIF
  169.  
  170.       /* delete this confirmation message */
  171.       DeleteArgstring(rexxargs[0])
  172.       DeleteRexxMsg(rexxmsg)
  173.  
  174.       /* decrease unconfirmed count */
  175.       DEC unconfirmed
  176.  
  177.     /* a brand new message */
  178.     ELSE
  179.  
  180.       /* point to command after skipping spaces etc. */
  181.       command:=TrimStr(rexxargs[0])
  182.       WriteF('We received an ARexx command: \s\n',command)
  183.  
  184.       /* initialize the resultcodes */
  185.       rexxmsg.result1:=0
  186.       rexxmsg.result2:=NIL
  187.  
  188.       /* example of handling a command that someone sent to us
  189.          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  190.  
  191.       /* command known? */
  192.       IF StrCmp('QUIT',command,ALL)
  193.         WriteF('So let\as quit here.\n')
  194.         runflag:=FALSE
  195.         ReplyMsg(rexxmsg)
  196.  
  197.       /* command unknown */
  198.       ELSE
  199.         WriteF('Hmmm. Unknown command. Let\as send it to Rexx Master...\n')
  200.  
  201.         /* forward this command to rexx master (maybe it's a script?) */
  202.         /* the original unknown command message is not yet replied to */
  203.         /* until we receive a confirmation from rexx master.          */
  204.  
  205.         /* therefore we remember this message by storing a messagepointer */
  206.         /* in rexxargs[15] of the forwarded command to Rexx Master        */
  207.  
  208.         /* message can not be sent to rexx? */
  209.         IF sendRexxMsg('REXX',rexxargs[0],rexxmsg,0)=NIL
  210.  
  211.           /* set fatal error returncodes */
  212.           xReplyRexxCmd(rexxmsg,RC_FATAL,NIL)
  213.  
  214.           /* reply the message */
  215.           ReplyMsg(rexxmsg)
  216.  
  217.         ENDIF
  218.       ENDIF
  219.     ENDIF
  220.   ENDWHILE
  221. ENDPROC
  222. /* FEND */
  223. /* FOLD "sendRexxMsg(hostname,command,unknownmsg,flags)" */
  224. PROC sendRexxMsg(hostname,command,unknownmsg,flags)
  225.  
  226.   DEF arexxport=NIL:PTR TO mp
  227.   DEF rexxmsg=NIL:PTR TO rexxmsg
  228.   DEF rexxargs:PTR TO LONG
  229.   DEF listnode=NIL:PTR TO ln
  230.   DEF temp=NIL
  231.  
  232.   /* return if hostport is not present */
  233.   IF hostport=NIL THEN RETURN NIL
  234.  
  235.   listnode:=hostport.ln
  236.  
  237.   /* return if we can't make a rexxmessage */
  238.   IF (rexxmsg:=CreateRexxMsg(hostport,'rexx',listnode.name))=NIL THEN RETURN NIL
  239.  
  240.   /* pointer to commands */
  241.   rexxargs:=rexxmsg.args
  242.  
  243.   /* can we create an argstring? */
  244.   IF temp:=CreateArgstring(command,StrLen(command))
  245.  
  246.     /* set the first argstring */
  247.     rexxargs[0]:=temp
  248.  
  249.     /* set the flags */
  250.     rexxmsg.action:=RXCOMM OR flags
  251.     
  252.     /* store original message pointer into 16th argstring pointer */
  253.     rexxargs[15]:=unknownmsg
  254.  
  255.     /* forbid multitasking */
  256.     Forbid()
  257.  
  258.     /* send our message to an existing port for sure */
  259.     IF (arexxport:=FindPort(hostname)) THEN PutMsg(arexxport,rexxmsg)
  260.  
  261.     /* permit multitasking */
  262.     Permit()
  263.  
  264.     /* sended? */
  265.     IF arexxport
  266.  
  267.       /* increase the unconfirmed counter */
  268.       INC unconfirmed
  269.  
  270.       /* successfully sent this message */
  271.       RETURN rexxmsg
  272.     ENDIF
  273.   ENDIF
  274.  
  275.   IF temp
  276.     DeleteArgstring(temp)
  277.   ENDIF
  278.   IF rexxmsg
  279.     DeleteRexxMsg(rexxmsg)
  280.   ENDIF
  281.   RETURN NIL
  282. ENDPROC
  283. /* FEND */
  284. /* FOLD "replyRexxMsg(rexxmsg,rc,returnstring)" */
  285. PROC xReplyRexxCmd(rexxmsg:PTR TO rexxmsg,rc,returnstring)
  286.  
  287.   /* set the returncode */
  288.   rexxmsg.result1:=rc
  289.  
  290.   /* and a pointer to the result string */
  291.   rexxmsg.result2:=IF (rexxmsg.action AND RXFF_RESULT) AND (returnstring<>NIL) THEN CreateArgstring(returnstring,StrLen(returnstring)) ELSE NIL
  292.  
  293. ENDPROC
  294. /* FEND */
  295. /* FOLD "createPort(portname,priority)" */
  296. PROC createPort(portname,priority)
  297.  
  298.   DEF port=NIL:PTR TO mp
  299.   DEF node=NIL:PTR TO ln
  300.  
  301.   /* make port public? */
  302.   IF portname
  303.  
  304.     /* no-one make the same port please */
  305.     Forbid()
  306.  
  307.     /* is our (soon to be) port unique? */
  308.     IF FindPort(portname)=0
  309.  
  310.       /* could we make a port? */
  311.       IF port:=CreateMsgPort()
  312.  
  313.         node:=port.ln
  314.  
  315.         /* fill in the name */
  316.         node.name:=portname
  317.  
  318.         /* public port priority */
  319.         node.pri:=priority
  320.  
  321.         /* and make this port public */
  322.         AddPort(port)
  323.       ENDIF
  324.     ENDIF
  325.  
  326.     /* multitask */
  327.     Permit()
  328.  
  329.   /* just make private port */
  330.   ELSE
  331.  
  332.     /* try to make a port */
  333.     port:=CreateMsgPort()
  334.  
  335.   ENDIF
  336. /* return pointer to port, or NIL if the port could not be made (unique) */
  337. ENDPROC port
  338. /* FEND */
  339. /* FOLD "deletePort(port)" */
  340. PROC deletePort(port:PTR TO mp)
  341.  
  342.   DEF node=NIL:PTR TO ln
  343.   DEF msg=NIL:PTR TO mn
  344.  
  345.   /* pointer given? */
  346.   IF port
  347.  
  348.     node:=port.ln
  349.  
  350.     /* if public then remove from public port list */
  351.     IF node.name THEN RemPort(port)
  352.  
  353.     /* no more messages please */
  354.     Forbid()
  355.  
  356.     /* remove all messages in queue */
  357.     WHILE msg:=GetMsg(port) DO ReplyMsg(msg)
  358.  
  359.     /* delete the port */
  360.     DeleteMsgPort(port)
  361.  
  362.     /* multitask */
  363.     Permit()
  364.   ENDIF
  365. ENDPROC
  366. /* FEND */
  367.  
  368.