home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 6 / FreshFish_September1994.bin / bbs / misc / cp-4.3.lha / cP / Source / simplerexx.c < prev    next >
C/C++ Source or Header  |  1994-03-02  |  10KB  |  419 lines

  1. /*
  2.  * Simple ARexx interface...
  3.  *
  4.  * This is a very "Simple" interface to the world of ARexx...
  5.  * For more complex interfaces into ARexx, it is best that you
  6.  * understand the functions that are provided by ARexx.
  7.  * In many cases they are more powerful than what is presented
  8.  * here.
  9.  *
  10.  * This code is fully re-entrant and self-contained other than
  11.  * the use of SysBase/AbsExecBase and the ARexx RVI support
  12.  * library which is also self-contained...
  13.  */
  14.  
  15. #include    <exec/types.h>
  16. #include    <exec/nodes.h>
  17. #include    <exec/lists.h>
  18. #include    <exec/ports.h>
  19. #include    <exec/memory.h>
  20.  
  21. #include    <proto/exec.h>
  22.  
  23. #include    <rexx/storage.h>
  24. #include    <rexx/rxslib.h>
  25.  
  26. #include    <string.h>
  27. #include    <ctype.h>
  28.  
  29. /*
  30.  * The prototypes for the few ARexx functions we will call...
  31.  */
  32. struct RexxMsg *CreateRexxMsg(struct MsgPort *,char *,char *);
  33. void *CreateArgstring(char *,long);
  34. void DeleteRexxMsg(struct RexxMsg *);
  35. void DeleteArgstring(char *);
  36. BOOL IsRexxMsg(struct Message *);
  37.  
  38. /*
  39.  * Pragmas for the above functions...  (To make this all self-contained...)
  40.  * If you use RexxGlue.o, this is not needed...
  41.  *
  42.  * These are for Lattice C 5.x  (Note the use of RexxContext->RexxSysBase)
  43.  */
  44. #pragma libcall RexxContext->RexxSysBase CreateRexxMsg 90 09803
  45. #pragma libcall RexxContext->RexxSysBase CreateArgstring 7E 0802
  46. #pragma libcall RexxContext->RexxSysBase DeleteRexxMsg 96 801
  47. #pragma libcall RexxContext->RexxSysBase DeleteArgstring 84 801
  48. #pragma libcall RexxContext->RexxSysBase IsRexxMsg A8 801
  49.  
  50. /*
  51.  * Prototypes for the RVI ARexx calls...  (link with RexxVars.o)
  52.  */
  53. /*
  54. __stdargs long CheckRexxMsg(struct RexxMsg *);
  55. __stdargs long GetRexxVar(struct RexxMsg *,char *,char **);
  56. __stdargs long SetRexxVar(struct RexxMsg *,char *,char *,long);
  57. */
  58. /*
  59.  * Now, we have made the pragmas needed, let's get to work...
  60.  */
  61.  
  62. /*
  63.  * A structure for the ARexx handler context
  64.  * This is *VERY* *PRIVATE* and should not be touched...
  65.  */
  66. struct    ARexxContext
  67. {
  68. struct    MsgPort    *ARexxPort;    /* The port messages come in at... */
  69. struct    Library    *RexxSysBase;    /* We will hide the library pointer here... */
  70.     long    Outstanding;    /* The count of outstanding ARexx messages... */
  71.     char    PortName[24];    /* The port name goes here... */
  72.     char    ErrorName[28];    /* The name of the <base>.LASTERROR... */
  73.     char    Extension[8];    /* Default file name extension... */
  74. };
  75.  
  76. #define    AREXXCONTEXT    struct ARexxContext *
  77.  
  78. #include    "SimpleRexx.h"
  79.  
  80. /*
  81.  * This function returns the port name of your ARexx port.
  82.  * It will return NULL if there is no ARexx port...
  83.  *
  84.  * This string is *READ ONLY*  You *MUST NOT* modify it...
  85.  */
  86. char *ARexxName(AREXXCONTEXT RexxContext)
  87. {
  88. register    char    *tmp=NULL;
  89.  
  90.     if (RexxContext) tmp=RexxContext->PortName;
  91.     return(tmp);
  92. }
  93.  
  94. /*
  95.  * This function returns the signal mask that the Rexx port is
  96.  * using.  It returns NULL if there is no signal...
  97.  *
  98.  * Use this signal bit in your Wait() loop...
  99.  */
  100. ULONG ARexxSignal(AREXXCONTEXT RexxContext)
  101. {
  102. register    ULONG    tmp=NULL;
  103.  
  104.     if (RexxContext) tmp=1L << (RexxContext->ARexxPort->mp_SigBit);
  105.     return(tmp);
  106. }
  107.  
  108. /*
  109.  * This function returns a structure that contains the commands sent from
  110.  * ARexx...  You will need to parse it and return the structure back
  111.  * so that the memory can be freed...
  112.  *
  113.  * This returns NULL if there was no message...
  114.  */
  115. struct RexxMsg *GetARexxMsg(AREXXCONTEXT RexxContext)
  116. {
  117. register    struct    RexxMsg    *tmp=NULL;
  118. register        short    flag;
  119.  
  120.     if (RexxContext)
  121.         if (tmp=(struct RexxMsg *)GetMsg(RexxContext->ARexxPort))
  122.     {
  123.         if (tmp->rm_Node.mn_Node.ln_Type==NT_REPLYMSG)
  124.         {
  125.             /*
  126.              * If we had sent a command, it would come this way...
  127.              *
  128.              * Since we don't in this simple example, we just throw
  129.              * away anything that looks "strange"
  130.              */
  131.             flag=FALSE;
  132.             if (tmp->rm_Result1) flag=TRUE;
  133.  
  134.             /*
  135.              * Free the arguments and the message...
  136.              */
  137.             DeleteArgstring(tmp->rm_Args[0]);
  138.             DeleteRexxMsg(tmp);
  139.             RexxContext->Outstanding-=1;
  140.  
  141.             /*
  142.              * Return the error if there was one...
  143.              */
  144.             tmp=flag ? REXX_RETURN_ERROR : NULL;
  145.         }
  146.     }
  147.     return(tmp);
  148. }
  149.  
  150. /*
  151.  * Use this to return a ARexx message...
  152.  *
  153.  * If you wish to return something, it must be in the RString.
  154.  * If you wish to return an Error, it must be in the Error.
  155.  * If there is an error, the RString is ignored.
  156.  */
  157. void ReplyARexxMsg(AREXXCONTEXT RexxContext,struct RexxMsg *rmsg,
  158.             char *RString,LONG Error)
  159. {
  160.     if (RexxContext) if (rmsg) if (rmsg!=REXX_RETURN_ERROR)
  161.     {
  162.         rmsg->rm_Result2=0;
  163.         if (!(rmsg->rm_Result1=Error))
  164.         {
  165.             /*
  166.              * if you did not have an error we return the string
  167.              */
  168.             if (rmsg->rm_Action & (1L << RXFB_RESULT)) if (RString)
  169.             {
  170.                 rmsg->rm_Result2=(LONG)CreateArgstring(RString,
  171.                             (LONG)strlen(RString));
  172.             }
  173.         }
  174.  
  175.         /*
  176.          * Reply the message to ARexx...
  177.          */
  178.         ReplyMsg((struct Message *)rmsg);
  179.     }
  180. }
  181.  
  182. /*
  183.  * This function will set an error string for the ARexx
  184.  * application in the variable defined as <appname>.LASTERROR
  185.  *
  186.  * Note that this can only happen if there is an ARexx message...
  187.  *
  188.  * This returns TRUE if it worked, FALSE if it did not...
  189.  */
  190. short SetARexxLastError(AREXXCONTEXT RexxContext,struct RexxMsg *rmsg,
  191.             char *ErrorString)
  192. {
  193. register    short    OkFlag=FALSE;
  194.  
  195.     if (RexxContext) if (rmsg) if (CheckRexxMsg((struct Message *)rmsg))
  196.     {
  197.         /*
  198.          * Note that SetRexxVar() has more than just a TRUE/FALSE
  199.          * return code, but for this "basic" case, we just care if
  200.          * it works or not.
  201.          */
  202.         if (!SetRexxVar((struct Message *)rmsg,RexxContext->ErrorName,ErrorString,
  203.                         (long)strlen(ErrorString)))
  204.         {
  205.             OkFlag=TRUE;
  206.         }
  207.     }
  208.     return(OkFlag);
  209. }
  210.  
  211. /*
  212.  * This function will send a string to ARexx...
  213.  *
  214.  * The default host port will be that of your task...
  215.  *
  216.  * If you set StringFile to TRUE, it will set that bit for the message...
  217.  *
  218.  * Returns TRUE if it send the message, FALSE if it did not...
  219.  */
  220. short SendARexxMsg(AREXXCONTEXT RexxContext,char *RString,
  221.             short StringFile)
  222. {
  223. register    struct    MsgPort    *RexxPort;
  224. register    struct    RexxMsg    *rmsg;
  225. register        short    flag=FALSE;
  226.  
  227.     if (RexxContext) if (RString)
  228.     {
  229.         if (rmsg=CreateRexxMsg(RexxContext->ARexxPort,
  230.                     RexxContext->Extension,
  231.                     RexxContext->PortName))
  232.         {
  233.             rmsg->rm_Action=RXCOMM | (StringFile ?
  234.                             (1L << RXFB_STRING):0);
  235.             if (rmsg->rm_Args[0]=CreateArgstring(RString,
  236.                             (LONG)strlen(RString)))
  237.             {
  238.                 /*
  239.                  * We need to find the RexxPort and this needs
  240.                  * to be done in a Forbid()
  241.                  */
  242.                 Forbid();
  243.                 if (RexxPort=FindPort(RXSDIR))
  244.                 {
  245.                     /*
  246.                      * We found the port, so put the
  247.                      * message to ARexx...
  248.                      */
  249.                     PutMsg(RexxPort,(struct Message *)rmsg);
  250.                     RexxContext->Outstanding+=1;
  251.                     flag=TRUE;
  252.                 }
  253.                 else
  254.                 {
  255.                     /*
  256.                      * No port, so clean up...
  257.                      */
  258.                     DeleteArgstring(rmsg->rm_Args[0]);
  259.                     DeleteRexxMsg(rmsg);
  260.                 }
  261.                 Permit();
  262.             }
  263.             else DeleteRexxMsg(rmsg);
  264.         }
  265.     }
  266.     return(flag);
  267. }
  268.  
  269. /*
  270.  * This function closes down the ARexx context that was opened
  271.  * with InitARexx...
  272.  */
  273. void FreeARexx(AREXXCONTEXT RexxContext)
  274. {
  275. register    struct    RexxMsg    *rmsg;
  276.  
  277.     if (RexxContext)
  278.     {
  279.         /*
  280.          * Clear port name so it can't be found...
  281.          */
  282.         RexxContext->PortName[0]='\0';
  283.  
  284.         /*
  285.          * Clean out any outstanding messages we had sent out...
  286.          */
  287.         while (RexxContext->Outstanding)
  288.         {
  289.             WaitPort(RexxContext->ARexxPort);
  290.             while (rmsg=GetARexxMsg(RexxContext))
  291.             {
  292.                 if (rmsg!=REXX_RETURN_ERROR)
  293.                 {
  294.                     /*
  295.                      * Any messages that come now are blown
  296.                      * away...
  297.                      */
  298.                     SetARexxLastError(RexxContext,rmsg,
  299.                                 "99: Port Closed!");
  300.                     ReplyARexxMsg(RexxContext,rmsg,
  301.                             NULL,100);
  302.                 }
  303.             }
  304.         }
  305.  
  306.         /*
  307.          * Clean up the port and delete it...
  308.          */
  309.         if (RexxContext->ARexxPort)
  310.         {
  311.             while (rmsg=GetARexxMsg(RexxContext))
  312.             {
  313.                 /*
  314.                  * Any messages that still are coming in are
  315.                  * "dead"  We just set the LASTERROR and
  316.                  * reply an error of 100...
  317.                  */
  318.                 SetARexxLastError(RexxContext,rmsg,
  319.                             "99: Port Closed!");
  320.                 ReplyARexxMsg(RexxContext,rmsg,NULL,100);
  321.             }
  322.             DeletePort(RexxContext->ARexxPort);
  323.         }
  324.  
  325.         /*
  326.          * Make sure we close the library...
  327.          */
  328.         if (RexxContext->RexxSysBase)
  329.         {
  330.             CloseLibrary(RexxContext->RexxSysBase);
  331.         }
  332.  
  333.         /*
  334.          * Free the memory of the RexxContext
  335.          */
  336.         FreeMem(RexxCon