home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 488.lha / modengine_v1.0 / mod_arexx.c < prev    next >
C/C++ Source or Header  |  1991-03-07  |  8KB  |  285 lines

  1. /* mod_arexx.c
  2.  * Copyright (C) 1990 Commodore-Amiga, Inc.
  3.  * written by David N. Junod
  4.  *
  5.  * AREXX message handling routines
  6.  *
  7.  */
  8.  
  9. #include "mod.h"
  10.  
  11. /* variables required for ARexx */
  12. struct ARexxInfo
  13. {
  14.     struct MsgPort *rxport;    /* ARexx message port */
  15.     UBYTE *portname;        /* ARexx message port name */
  16.     UBYTE *extens;        /* ARexx macro name extension */
  17.     BOOL astatus;        /* ARexx status */
  18.  
  19.     /* user call-back functions */
  20.     VOID (*ufunc[2])(struct AppInfo *, struct Message *, struct MsgHandler *);
  21. };
  22.  
  23. /* User call-back function pointers */
  24. #define ARX_MACRO_ERROR    0
  25. #define ARX_MACRO_GOOD    1
  26.  
  27. /* ARexx message handling routines */
  28. BOOL open_arexx (struct AppInfo *, struct MsgHandler * );
  29. BOOL handle_arexx (struct AppInfo *, struct MsgHandler * );
  30. BOOL close_arexx (struct AppInfo *, struct MsgHandler * );
  31. BOOL shutdown_arexx (struct AppInfo *, struct MsgHandler * );
  32.  
  33. BOOL send_rexx_command (UBYTE *, struct AppInfo *, struct MsgHandler *);
  34. VOID execute_command (struct RexxMsg *,struct AppInfo *,struct MsgHandler *);
  35. VOID reply_rexx_command (struct RexxMsg *,struct AppInfo *,struct MsgHandler *);
  36.  
  37. /* ARexx Functions Prototypes */
  38. struct RexxMsg *CreateRexxMsg (struct MsgPort *, UBYTE *, UBYTE *);
  39. STRPTR CreateArgstring (UBYTE *, int);
  40. VOID DeleteRexxMsg (struct RexxMsg *);
  41. VOID DeleteArgstring (UBYTE *);
  42. BOOL IsRexxMsg (struct Message *);
  43.  
  44. /* Required for ARexx processing */
  45. struct RxsLib *RexxSysBase = NULL;
  46.  
  47. struct MsgHandler *setup_arexx (struct AppInfo * ai, UBYTE * pname,
  48.                 UBYTE * extens, BOOL immed)
  49. {
  50.     UBYTE *portname = "                        ";
  51.     register WORD cntr = 1;
  52.     BOOL exist = TRUE, retval = FALSE;
  53.     struct MsgHandler *mh = NULL;
  54.     struct ARexxInfo *md = NULL;
  55.  
  56.     if (md = (struct ARexxInfo *)
  57.     AllocMem (sizeof (struct ARexxInfo), MEMF_CLEAR|MEMF_PUBLIC))
  58.     {
  59.     md->portname = pname;
  60.     md->extens = extens;
  61.     if (RexxSysBase = (struct RsxLib *)
  62.         OpenLibrary ("rexxsyslib.library", 0L))
  63.     {
  64.  
  65.         /* forbid multi-tasking while we try to get a port */
  66.         Forbid ();
  67.  
  68.         /* get an unique port name */
  69.         while (exist)
  70.         {
  71.         /* create a name with our base name and a number */
  72.         sprintf (portname, "%s_%d", md->portname, cntr);
  73.  
  74.         /* see if someone has already taken this name */
  75.         if (!FindPort (portname))
  76.             exist = FALSE;
  77.         cntr++;
  78.         }
  79.  
  80.         /* allocate the port */
  81.         if (md->rxport = CreatePort (portname, 0L))
  82.         retval = TRUE;
  83.  
  84.         /* permit multi-tasking again */
  85.         Permit ();
  86.  
  87.         if (mh = (struct MsgHandler *)
  88.         AllocMem (sizeof (struct MsgHandler), MEMF_CLEAR|MEMF_PUBLIC))
  89.         {
  90.         mh->mh_Node.ln_Type = MH_HANDLER_T;
  91.         mh->mh_Node.ln_Pri  = MH_HANDLER_P;
  92.         mh->mh_Node.ln_Name = "AREXX";
  93.         mh->mh_SigBits = (1L << md->rxport->mp_SigBit);
  94.         mh->mh_Func[MH_OPEN]     = open_arexx;
  95.         mh->mh_Func[MH_HANDLE]   = handle_arexx;
  96.         mh->mh_Func[MH_CLOSE]    = close_arexx;
  97.         mh->mh_Func[MH_SHUTDOWN] = shutdown_arexx;
  98.         mh->mh_Data = md;
  99.  
  100.         /* open immediately? */
  101.         if (immed)
  102.         {
  103.             if (open_arexx (ai, mh))
  104.             return (mh);
  105.         }
  106.         else
  107.             return (mh);
  108.  
  109.         FreeMem (mh, sizeof (struct MsgHandler));
  110.         }
  111.         else
  112.         NotifyUser (NULL, "Not enough memory");
  113.  
  114.         /* make a nice clean failure path */
  115.         DeletePort (md->rxport);
  116.         CloseLibrary ((struct Library *) RexxSysBase);
  117.         md->rxport = NULL;
  118.         RexxSysBase = NULL;
  119.     }
  120.     else
  121.         NotifyUser (NULL, "Could not open rexxsyslib.library");
  122.  
  123.     FreeMem (md, sizeof (struct ARexxInfo));
  124.     }
  125.     return (mh);
  126. }
  127.  
  128. BOOL open_arexx (struct AppInfo * ai, struct MsgHandler * mh)
  129. {
  130.     ((struct ARexxInfo *)mh->mh_Data)->astatus = AR_EXECUTE;
  131.     return (TRUE);
  132. }
  133.  
  134. /* ARexx message processing */
  135. BOOL handle_arexx (struct AppInfo * ai, struct MsgHandler * mh)
  136. {
  137.     struct RexxMsg *rmsg;    /* incoming ARexx messages */
  138.     struct ARexxInfo * md = mh->mh_Data;
  139.  
  140.     while (rmsg = (struct RexxMsg *) GetMsg (md->rxport))
  141.     {
  142.     if (rmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
  143.     {
  144.         /* This is a reply to a previous message */
  145.         if (rmsg->rm_Result1)
  146.         {
  147.         /* returned an error message, perform user call-back */
  148.         if (md->ufunc[ARX_MACRO_ERROR])
  149.             (*md->ufunc[ARX_MACRO_ERROR])
  150.             (ai, (struct Message *) rmsg, mh);
  151.         }
  152.         else
  153.         {
  154.         /* successful return, perform user call-back */
  155.         if (md->ufunc[ARX_MACRO_GOOD])
  156.             (*md->ufunc[ARX_MACRO_GOOD])
  157.             (ai, (struct Message *) rmsg, mh);
  158.         }
  159.         /* delete the argument that we originally sent */
  160.         DeleteArgstring (rmsg->rm_Args[0]);
  161.  
  162.         /* delete the extended message */
  163.         DeleteRexxMsg (rmsg);
  164.  
  165.         /* decrement the count of outstanding messages */
  166.         ai->numcmds--;
  167.     }
  168.     else
  169.         /* We have received a command/function message */
  170.         execute_command (rmsg, ai, mh);
  171.     }
  172.     return (TRUE);
  173. }
  174.  
  175. BOOL close_arexx (struct AppInfo * ai, struct MsgHandler * mh)
  176. {
  177.     ((struct ARexxInfo *)mh->mh_Data)->astatus = AR_SUSPEND;
  178.     return (TRUE);
  179. }
  180.  
  181. BOOL shutdown_arexx (struct AppInfo * ai, struct MsgHandler * mh)
  182. {
  183.     struct ARexxInfo * md = mh->mh_Data;
  184.  
  185.     if (mh)
  186.     {
  187.     if (md->rxport)
  188.         DeletePort (md->rxport);
  189.  
  190.     Remove ((struct Node *) mh);
  191.     FreeMem (mh, sizeof (struct MsgHandler));
  192.     }
  193.     if (RexxSysBase)
  194.     CloseLibrary ((struct Library *) RexxSysBase);
  195.     RexxSysBase = NULL;
  196.     return (TRUE);
  197. }
  198.  
  199. BOOL send_rexx_command (UBYTE * buff, struct AppInfo * ai,
  200.             struct MsgHandler * mh)
  201. {
  202.     struct MsgPort *rexxport;    /* this will be rexx's port */
  203.     struct RexxMsg *rexx_command_message;    /* this is the message */
  204.     struct ARexxInfo * md = mh->mh_Data;
  205.  
  206.     /* lock things temporarily */
  207.     Forbid ();
  208.  
  209.     /* if ARexx is not active, just return FALSE */
  210.     if (!(rexxport = FindPort (RXSDIR)))
  211.     {
  212.     Permit ();
  213.     return (FALSE);
  214.     }
  215.  
  216.     /* allocate a message packet for our command */
  217.     /* note that this is a very important call.  Much flexibility is */
  218.     /* available to you here by using multiple host port names, etc. */
  219.     if (!(rexx_command_message = CreateRexxMsg (md->rxport,
  220.                         md->extens,
  221.                         md->rxport->mp_Node.ln_Name)))
  222.     {
  223.     Permit ();
  224.     return (FALSE);
  225.     }
  226.  
  227.     /* create an argument string and install it in the message */
  228.     if (!(rexx_command_message->rm_Args[0] =
  229.       CreateArgstring (buff, strlen (buff))))
  230.     {
  231.     DeleteRexxMsg (rexx_command_message);
  232.     Permit ();
  233.     return (FALSE);
  234.     }
  235.  
  236.     /* indicate that message is a command */
  237.     rexx_command_message->rm_Action = RXCOMM;
  238.  
  239.     /* send the message */
  240.     PutMsg (rexxport, (struct Message *) rexx_command_message);
  241.  
  242.     /* increment the number of outstanding messages */
  243.     ai->numcmds++;
  244.  
  245.     Permit ();
  246.     return (TRUE);
  247. }
  248.  
  249. VOID execute_command (struct RexxMsg * rmsg, struct AppInfo * ai,
  250.               struct MsgHandler * mh)
  251. {
  252.     struct ARexxInfo * md = mh->mh_Data;
  253.     UBYTE *cmd = ARG0 (rmsg);
  254.  
  255.     /* preset the ARexx error return values */
  256.     ai->pri_ret = 5L;
  257.     ai->sec_ret = 0L;
  258.     ai->textrtn = NULL;
  259.  
  260.     /* Don't perform function if we are suspended */
  261.     if (md->astatus == AR_EXECUTE)
  262.     PerfFunc (ai, (struct Message *) rmsg, cmd);
  263.     else
  264.     ai->pri_ret = 100L;
  265.  
  266.     /* reply to the message */
  267.     reply_rexx_command (rmsg, ai, mh);
  268. }
  269.  
  270. /* Replys to a ARexx message */
  271. VOID reply_rexx_command (struct RexxMsg * rmsg, struct AppInfo * ai,
  272.              struct MsgHandler * mh)
  273. {
  274.     /* set an error code */
  275.     if (ai->pri_ret == 0 && (rmsg->rm_Action & 1L << RXFB_RESULT))
  276.     {
  277.     ai->sec_ret = ai->textrtn ?
  278.     (LONG) CreateArgstring (ai->textrtn, strlen (ai->textrtn))
  279.     : (LONG) NULL;
  280.     }
  281.     rmsg->rm_Result1 = ai->pri_ret;
  282.     rmsg->rm_Result2 = ai->sec_ret;
  283.     ReplyMsg ((struct Message *) rmsg);
  284. }
  285.