home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / ARexx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  17.9 KB  |  1,026 lines

  1. /*
  2. **    ARexx.c
  3. **
  4. **    ARexx interface general support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #ifndef _GLOBAL_H
  11. #include "Global.h"
  12. #endif
  13.  
  14.     /* IsNumeric(STRPTR String):
  15.      *
  16.      *    Is the string really a number?
  17.      */
  18.  
  19. BOOL
  20. IsNumeric(STRPTR String)
  21. {
  22.     while(*String && (*String == ' ' || *String == '\t'))
  23.         String++;
  24.  
  25.     while(*String)
  26.     {
  27.         if(*String < '0' || *String > '9')
  28.             return(FALSE);
  29.         else
  30.             String++;
  31.     }
  32.  
  33.     return(TRUE);
  34. }
  35.  
  36.     /* CreateResult(STRPTR ResultString,LONG *Results):
  37.      *
  38.      *    Create a proper Rexx result string.
  39.      */
  40.  
  41. STRPTR
  42. CreateResult(STRPTR ResultString,LONG *Results)
  43. {
  44.     STRPTR Result;
  45.  
  46.     if(!(Result = CreateArgstring(ResultString,strlen(ResultString))))
  47.     {
  48.         Results[0] = RC_ERROR;
  49.         Results[1] = ERROR_NO_FREE_STORE;
  50.     }
  51.  
  52.     return(Result);
  53. }
  54.  
  55.     /* CreateResultLen(STRPTR ResultString,LONG *Results):
  56.      *
  57.      *    Create a proper Rexx result string given the
  58.      *    length of the source string.
  59.      */
  60.  
  61. STRPTR
  62. CreateResultLen(STRPTR ResultString,LONG *Results,LONG Len)
  63. {
  64.     STRPTR Result;
  65.  
  66.     if(!(Result = CreateArgstring(ResultString,Len)))
  67.     {
  68.         Results[0] = RC_ERROR;
  69.         Results[1] = ERROR_NO_FREE_STORE;
  70.     }
  71.  
  72.     return(Result);
  73. }
  74.  
  75.     /* CreateVarArgs(STRPTR Value,struct RexxPkt *Packet,STRPTR Stem,...):
  76.      *
  77.      *    Set a Rexx variable, special treatment.
  78.      */
  79.  
  80. BOOL __stdargs
  81. CreateVarArgs(STRPTR Value,struct RexxPkt *Packet,STRPTR Stem,...)
  82. {
  83.     UBYTE    Name[256];
  84.     va_list    VarArgs;
  85.     LONG    Result;
  86.  
  87.     va_start(VarArgs,Stem);
  88.     VSPrintf(Name,Stem,VarArgs);
  89.     va_end(VarArgs);
  90.  
  91.     if(Result = SetRexxVar(Packet -> RexxMsg,Name,Value,strlen(Value)))
  92.     {
  93.         Packet -> Results[0] = RC_ERROR;
  94.         Packet -> Results[1] = Result;
  95.  
  96.         return(FALSE);
  97.     }
  98.     else
  99.         return(TRUE);
  100. }
  101.  
  102.     /* CreateVar(STRPTR Value,struct RexxPkt *Packet,STRPTR Name):
  103.      *
  104.      *    Set a Rexx variable, simple version.
  105.      */
  106.  
  107. STRPTR
  108. CreateVar(STRPTR Value,struct RexxPkt *Packet,STRPTR Name)
  109. {
  110.     LONG Result;
  111.  
  112.     if(Result = SetRexxVar(Packet -> RexxMsg,Name,Value,strlen(Value)))
  113.     {
  114.         Packet -> Results[0] = RC_ERROR;
  115.         Packet -> Results[1] = Result;
  116.     }
  117.  
  118.     return(NULL);
  119. }
  120.  
  121.     /* CreateMatchBuffer(STRPTR Pattern):
  122.      *
  123.      *    Create a pattern buffer suitable for pattern matching.
  124.      */
  125.  
  126. STRPTR
  127. CreateMatchBuffer(STRPTR Pattern)
  128. {
  129.     LONG    Len = strlen(Pattern) + 1;
  130.     STRPTR    Buffer;
  131.  
  132.     if(Buffer = (STRPTR)AllocVecPooled(2 * Len,MEMF_ANY))
  133.     {
  134.         if(ParsePatternNoCase(Pattern,Buffer,2 * Len) != -1)
  135.             return(Buffer);
  136.         else
  137.             FreeVecPooled(Buffer);
  138.     }
  139.  
  140.     return(NULL);
  141. }
  142.  
  143.     /* MatchBuffer(STRPTR Buffer,STRPTR Name):
  144.      *
  145.      *    Match a pattern against a string.
  146.      */
  147.  
  148. BOOL
  149. MatchBuffer(STRPTR Buffer,STRPTR Name)
  150. {
  151.     return((BOOL)(MatchPatternNoCase(Buffer,Name) != FALSE));
  152. }
  153.  
  154.     /* DeleteMatchBuffer(STRPTR Buffer):
  155.      *
  156.      *    Free a pattern matching buffer.
  157.      */
  158.  
  159. VOID
  160. DeleteMatchBuffer(STRPTR Buffer)
  161. {
  162.     FreeVecPooled(Buffer);
  163. }
  164.  
  165.     /* ToMode(STRPTR Name):
  166.      *
  167.      *    Turn a transfer mode name into a key.
  168.      */
  169.  
  170. LONG
  171. ToMode(STRPTR Name)
  172. {
  173.     STATIC STRPTR TransferModes[] =
  174.     {
  175.         "BINARY",
  176.         "TEXT",
  177.         "ASCII",
  178.         NULL
  179.     };
  180.  
  181.     LONG i;
  182.  
  183.     for(i = 0 ; TransferModes[i] ; i++)
  184.     {
  185.         if(!Stricmp(Name,TransferModes[i]))
  186.             return(i);
  187.     }
  188.  
  189.     return(-1);
  190. }
  191.  
  192.     /* ToList(STRPTR Name):
  193.      *
  194.      *    Turn a list name into a key.
  195.      */
  196.  
  197. LONG
  198. ToList(STRPTR Name)
  199. {
  200.     STATIC STRPTR ListTypes[GLIST_COUNT] =
  201.     {
  202.         "UPLOAD",
  203.         "DOWNLOAD",
  204.         "DIAL",
  205.         "WAIT",
  206.         "TRAP"
  207.     };
  208.  
  209.     LONG i;
  210.  
  211.     for(i = 0 ; i < GLIST_COUNT ; i++)
  212.     {
  213.         if(!Stricmp(Name,ListTypes[i]))
  214.             return(i);
  215.     }
  216.  
  217.     return(-1);
  218. }
  219.  
  220.     /* ToConfig(STRPTR Name):
  221.      *
  222.      *    Turn a configuration name into a key.
  223.      */
  224.  
  225. LONG
  226. ToConfig(STRPTR Name)
  227. {
  228.     STATIC STRPTR DataTypes[DATATYPE_COUNT] =
  229.     {
  230.         "TRANSLATIONS",
  231.         "FUNCTIONKEYS",
  232.         "CURSORKEYS",
  233.         "FASTMACROS",
  234.         "HOTKEYS",
  235.         "SPEECH",
  236.         "SOUND",
  237.         "BUFFER",
  238.         "CONFIGURATION",
  239.         "PHONE",
  240.         "SCREENTEXT",
  241.         "SCREENIMAGE"
  242.     };
  243.  
  244.     LONG i;
  245.  
  246.     for(i = 0 ; i < DATATYPE_COUNT ; i++)
  247.     {
  248.         if(!Stricmp(Name,DataTypes[i]))
  249.             return(i);
  250.     }
  251.  
  252.     return(-1);
  253. }
  254.  
  255.     /* ToRequester(STRPTR Name):
  256.      *
  257.      *    Turn a requester name into a key.
  258.      */
  259.  
  260. LONG
  261. ToRequester(STRPTR Name)
  262. {
  263.     STRPTR RequesterTypes[REQUESTER_COUNT] =
  264.     {
  265.         "SERIAL",
  266.         "MODEM",
  267.         "SCREEN",
  268.         "TERMINAL",
  269.         "EMULATION",
  270.         "CLIPBOARD",
  271.         "CAPTURE",
  272.         "COMMANDS",
  273.         "MISC",
  274.         "PATH",
  275.         "TRANSFER",
  276.         "TRANSLATIONS",
  277.         "FUNCTIONKEYS",
  278.         "CURSORKEYS",
  279.         "FASTMACROS",
  280.         "HOTKEYS",
  281.         "SPEECH",
  282.         "SOUND",
  283.         "PHONE"
  284.     };
  285.  
  286.     LONG i;
  287.  
  288.     for(i = 0 ; i < REQUESTER_COUNT ; i++)
  289.     {
  290.         if(!Stricmp(Name,RequesterTypes[i]))
  291.             return(i);
  292.     }
  293.  
  294.     return(-1);
  295. }
  296.  
  297.     /* ToWindow(STRPTR Name):
  298.      *
  299.      *    Turn a window name into a key.
  300.      */
  301.  
  302. LONG
  303. ToWindow(STRPTR Name)
  304. {
  305.     STATIC STRPTR WindowTypes[WINDOWID_COUNT] =
  306.     {
  307.         "BUFFER",
  308.         "REVIEW",
  309.         "PACKET",
  310.         "FASTMACROS",
  311.         "STATUS",
  312.         "MAIN",
  313.         "UPLOADQUEUE",
  314.         "SINGLECHARENTRY"
  315.     };
  316.  
  317.     LONG i;
  318.  
  319.     for(i = 0 ; i < WINDOWID_COUNT ; i++)
  320.     {
  321.         if(!Stricmp(WindowTypes[i],Name))
  322.             return(i);
  323.     }
  324.  
  325.     return(-1);
  326. }
  327.  
  328.     /* ReplyRexxCommand():
  329.      *
  330.      *    Reply a command request the rexx server - or someone else -
  331.      *    has passed to us.
  332.      */
  333.  
  334. STATIC VOID
  335. ReplyRexxCommand(struct RexxMsg *RexxMessage,LONG Primary,LONG Secondary)
  336. {
  337.     if(RexxMessage)
  338.     {
  339.         RexxMessage -> rm_Result1 = Primary;
  340.         RexxMessage -> rm_Result2 = Secondary;
  341.  
  342.         ReplyMsg(RexxMessage);
  343.     }
  344. }
  345.  
  346.     /* RexxToolServer(VOID):
  347.      *
  348.      *    Asynchronous tool/rexx command execution process.
  349.      */
  350.  
  351. STATIC VOID __saveds
  352. RexxToolServer(VOID)
  353. {
  354.     struct Process    *ThisProcess = (struct Process *)FindTask(NULL);
  355.     struct RexxPkt    *Packet;
  356.     BPTR         NewCOS    = NULL;
  357.  
  358.         /* Wait for startup packet. */
  359.  
  360.     WaitPort(&ThisProcess -> pr_MsgPort);
  361.  
  362.     Packet = (struct RexxPkt *)GetMsg(&ThisProcess -> pr_MsgPort);
  363.  
  364.         /* Increment usage count. */
  365.  
  366.     ObtainSemaphore(&RexxLaunchSemaphore);
  367.  
  368.     RexxLaunchCount++;
  369.  
  370.     ReleaseSemaphore(&RexxLaunchSemaphore);
  371.  
  372.         /* Create proper output stream if necessary. */
  373.  
  374.     if(!Output() && GetConsoleTask())
  375.     {
  376.         if(NewCOS = Open("CONSOLE:",MODE_NEWFILE))
  377.             SelectOutput(NewCOS);
  378.     }
  379.  
  380.         /* Execute the command. */
  381.  
  382.     (*Packet -> CommandInfo -> Routine)(Packet);
  383.  
  384.     Forbid();
  385.  
  386.         /* Decrement usage count. */
  387.  
  388.     ObtainSemaphore(&RexxLaunchSemaphore);
  389.  
  390.     RexxLaunchCount--;
  391.  
  392.     ReleaseSemaphore(&RexxLaunchSemaphore);
  393.  
  394.         /* Close the output stream. */
  395.  
  396.     if(NewCOS)
  397.     {
  398.         SelectOutput(NULL);
  399.  
  400.         Close(NewCOS);
  401.     }
  402.  
  403.         /* Return the message packet. */
  404.  
  405.     ReplyMsg((struct Message *)Packet);
  406. }
  407.  
  408.     /* InvokeRexxCommand(struct RexxPkt *Packet):
  409.      *
  410.      *    Invoke an ARexx command.
  411.      */
  412.  
  413. STATIC BOOL
  414. InvokeRexxCommand(struct RexxPkt *Packet)
  415. {
  416.         /* Asynchronous command? */
  417.  
  418.     if(Packet -> CommandInfo -> Async)
  419.     {
  420.             /* Requires special execution code? */
  421.  
  422.         if(Packet -> CommandInfo -> Tool)
  423.         {
  424.             struct RexxPkt *NewPacket;
  425.  
  426.                 /* Create a command packet. */
  427.  
  428.             if(NewPacket = (struct RexxPkt *)AllocVecPooled(sizeof(struct RexxPkt),MEMF_ANY | MEMF_PUBLIC))
  429.             {
  430.                 enum    {    ARG_CONSOLE };
  431.  
  432.                 struct Process    *NewProcess;
  433.                 BPTR         Stream;
  434.  
  435.                     /* Set up the command packet. */
  436.  
  437.                 CopyMem(Packet,NewPacket,sizeof(struct RexxPkt));
  438.  
  439.                 NewPacket -> VanillaMessage . mn_ReplyPort    = RexxPort;
  440.                 NewPacket -> VanillaMessage . mn_Length        = sizeof(struct RexxPkt);
  441.  
  442.                     /* Create I/O streams. */
  443.  
  444.                 if(Packet -> Array[ARG_CONSOLE] && WindowName[0] && Packet -> CommandInfo -> Console)
  445.                     Stream = Open(WindowName,MODE_NEWFILE);
  446.                 else
  447.                     Stream = NULL;
  448.  
  449.                     /* Launch the process. */
  450.  
  451.                 if(NewProcess = LaunchProcess("term Rexx Tool Process",RexxToolServer,Stream))
  452.                     PutMsg(&NewProcess -> pr_MsgPort,(struct Message *)NewPacket);
  453.                 else
  454.                 {
  455.                     FreeVecPooled(NewPacket);
  456.  
  457.                     ReplyRexxCommand(Packet -> RexxMsg,-1,0);
  458.  
  459.                     if(Stream)
  460.                         Close(Stream);
  461.                 }
  462.             }
  463.             else
  464.                 ReplyRexxCommand(Packet -> RexxMsg,-1,0);
  465.         }
  466.         else
  467.         {
  468.                 /* Execute the command on the schedule of the
  469.                  * rexx server process.
  470.                  */
  471.  
  472.             STRPTR Result = (*Packet -> CommandInfo -> Routine)(Packet);
  473.  
  474.             RexxPktCleanup(Packet,Result);
  475.         }
  476.     }
  477.     else
  478.     {
  479.         struct RexxPkt *NewPacket;
  480.  
  481.             /* Create message packet. */
  482.  
  483.         if(NewPacket = (struct RexxPkt *)AllocVecPooled(sizeof(struct RexxPkt),MEMF_ANY | MEMF_PUBLIC))
  484.         {
  485.                 /* Set up message packet. */
  486.  
  487.             CopyMem(Packet,NewPacket,sizeof(struct RexxPkt));
  488.  
  489.             NewPacket -> VanillaMessage . mn_ReplyPort    = RexxPort;
  490.             NewPacket -> VanillaMessage . mn_Length        = sizeof(struct RexxPkt);
  491.  
  492.                 /* Post it. */
  493.  
  494.             PutMsg(TermRexxPort,(struct Message *)NewPacket);
  495.         }
  496.         else
  497.             ReplyRexxCommand(Packet -> RexxMsg,-1,0);
  498.     }
  499.  
  500.     return(TRUE);
  501. }
  502.  
  503.     /* ParseRexxCommand(struct RexxMsg *RexxMsg):
  504.      *
  505.      *    Handles the synchronous Rexx commands and returns the
  506.      *    message if no matching command is found.
  507.      */
  508.  
  509. STATIC BOOL
  510. ParseRexxCommand(struct RexxMsg *RexxMsg)
  511. {
  512.     UBYTE    CommandBuffer[30];
  513.     STRPTR    Command,
  514.         CommandArgs;
  515.     LONG    Len = 0;
  516.  
  517.         /* Clear the local variables. */
  518.  
  519.     CommandBuffer[0]    = 0;
  520.     Command            = RexxMsg -> rm_Args[0];
  521.     CommandArgs        = NULL;
  522.  
  523.         /* Skip leading blank spaces. */
  524.  
  525.     while(*Command && (*Command == ' ' || *Command == '\t'))
  526.         Command++;
  527.  
  528.         /* Extract the command name. */
  529.  
  530.     do
  531.     {
  532.             /* Found the end of the string? */
  533.  
  534.         if(!Command[Len])
  535.         {
  536.                 /* Copy the command name. */
  537.  
  538.             strcpy(CommandBuffer,Command);
  539.  
  540.                 /* No arguments are provided. */
  541.  
  542.             CommandArgs = NULL;
  543.  
  544.             break;
  545.         }
  546.  
  547.             /* Found a blank space? */
  548.  
  549.         if(Command[Len] == ' ' || Command[Len] == '\t')
  550.         {
  551.                 /* Copy the command name. */
  552.  
  553.             CopyMem(Command,CommandBuffer,Len);
  554.  
  555.             CommandBuffer[Len] = 0;
  556.  
  557.                 /* Look for any arguments. */
  558.  
  559.             CommandArgs = &Command[Len + 1];
  560.  
  561.                 /* Skip blank spaces. */
  562.  
  563.             while(*CommandArgs && (*CommandArgs == ' ' || *CommandArgs == '\t'))
  564.                 CommandArgs++;
  565.  
  566.             break;
  567.         }
  568.     }
  569.     while(++Len < 30);
  570.  
  571.         /* Did we find a command name? */
  572.  
  573.     if(CommandBuffer[0])
  574.     {
  575.         struct CommandInfo    *CommandInfo = NULL;
  576.         LONG             CommandIndex;
  577.  
  578.             /* Which command is it? */
  579.  
  580.         for(CommandIndex = 0 ; CommandIndex < CommandTableSize ; CommandIndex++)
  581.         {
  582.             if(!Stricmp(CommandBuffer,CommandTable[CommandIndex] . Name))
  583.             {
  584.                 CommandInfo = &CommandTable[CommandIndex];
  585.  
  586.                 break;
  587.             }
  588.         }
  589.  
  590.             /* Did we find the command? */
  591.  
  592.         if(CommandInfo)
  593.         {
  594.             struct RexxPkt __aligned    Packet;
  595.             BOOL                Processed = FALSE;
  596.  
  597.                 /* Set the result codes to defaults. */
  598.  
  599.             Packet . Results[0]    = RC_OK;
  600.             Packet . Results[1]    = 0;
  601.  
  602.                 /* Fill in the rest. */
  603.  
  604.             Packet . CommandInfo    = CommandInfo;
  605.             Packet . RexxMsg    = RexxMsg;
  606.  
  607.                 /* Does this command accept any arguments? */
  608.  
  609.             if(CommandInfo -> Arguments)
  610.             {
  611.                 LONG *Array;
  612.  
  613.                     /* Determine length of argument string. */
  614.  
  615.                 if(CommandArgs)
  616.                     Len = strlen(CommandArgs);
  617.                 else
  618.                     Len = 0;
  619.  
  620.                     /* Allocate temporary buffer, we will need to
  621.                      * attach a line-feed character to the argument
  622.                      * string.
  623.                      */
  624.  
  625.                 if(Array = (LONG *)AllocVecPooled(12 * sizeof(LONG) + Len + 2,MEMF_ANY | MEMF_CLEAR | MEMF_PUBLIC))
  626.                 {
  627.                     STRPTR         Buffer;
  628.                     struct RDArgs    *Args;
  629.  
  630.                         /* Get the argument buffer. */
  631.  
  632.                     Buffer = (STRPTR)&Array[12];
  633.  
  634.                         /* Copy the argument string. */
  635.  
  636.                     if(CommandArgs && Len)
  637.                         CopyMem(CommandArgs,Buffer,Len);
  638.  
  639.                         /* Attach the line-feed character. */
  640.  
  641.                     Buffer[Len] = '\n';
  642.  
  643.                         /* Allocate argument parser data. */
  644.  
  645.                     if(Args = (struct RDArgs *)AllocDosObjectTags(DOS_RDARGS,TAG_DONE))
  646.                     {
  647.                         Packet . Array    = (STRPTR *)Array;
  648.                         Packet . Args    = Args;
  649.  
  650.                             /* Don't prompt for input! */
  651.  
  652.                         Args -> RDA_Flags |= RDAF_NOPROMPT;
  653.  
  654.                             /* Set up parser data. */
  655.  
  656.                         Args -> RDA_Source . CS_Buffer    = Buffer;
  657.                         Args -> RDA_Source . CS_Length    = Len + 1;
  658.                         Args -> RDA_Source . CS_CurChr    = 0;
  659.  
  660.                             /* Parse the arguments. */
  661.  
  662.                         if(ReadArgs(CommandInfo -> Arguments,Array,Args))
  663.                         {
  664.                             UWORD    Inclusion    = InclusionTable[CommandIndex];
  665.                             BOOL    ArgsRequired    = FALSE;
  666.                             LONG    i,Counted;
  667.  
  668.                                 /* Look for required arguments. */
  669.  
  670.                             for(i = Counted = 0 ; i < 12 ; i++)
  671.                             {
  672.                                 if(Inclusion & (1L << i))
  673.                                 {
  674.                                     ArgsRequired = TRUE;
  675.  
  676.                                     if(Array[i])
  677.                                         Counted++;
  678.                                 }
  679.                             }
  680.  
  681.                                 /* Are any arguments required
  682.                                  * but not provided?
  683.                                  */
  684.  
  685.                             if(ArgsRequired && !Counted)
  686.                             {
  687.                                 Packet . Results[0] = RC_ERROR;
  688.                                 Packet . Results[1] = ERROR_REQUIRED_ARG_MISSING;
  689.                             }
  690.                             else
  691.                             {
  692.                                 struct ExclusionInfo *Exclusion = ExclusionTable[CommandIndex];
  693.  
  694.                                     /* Any mutually-exclusive arguments? */
  695.  
  696.                                 if(Exclusion)
  697.                                 {
  698.                                     BOOL ArgsOkay = TRUE;
  699.  
  700.                                     i = 0;
  701.  
  702.                                         /* Look for arguments to
  703.                                          * exclude each other.
  704.                                          */
  705.  
  706.                                     while(ArgsOkay && Exclusion[i] . A != -1)
  707.                                     {
  708.                                         if(Array[Exclusion[i] . A] && Array[Exclusion[i] . B])
  709.                                             ArgsOkay = FALSE;
  710.                                         else
  711.                                             i++;
  712.                                     }
  713.  
  714.                                         /* All arguments correct? */
  715.  
  716.                                     if(ArgsOkay)
  717.                                         Processed = InvokeRexxCommand(&Packet);
  718.                                     else
  719.                                     {
  720.                                         Packet . Results[0] = RC_ERROR;
  721.                                         Packet . Results[1] = ERROR_TOO_MANY_ARGS;
  722.                                     }
  723.                                 }
  724.                                 else
  725.                                     Processed = InvokeRexxCommand(&Packet);
  726.                             }
  727.  
  728.                                 /* Free allocated parser data. */
  729.  
  730.                             if(!Processed)
  731.                                 FreeArgs(Args);
  732.                         }
  733.                         else
  734.                         {
  735.                             LONG Error = IoErr();
  736.  
  737.                             SetIoErr(Error);
  738.  
  739.                             Packet . Results[0] = RC_ERROR;
  740.                             Packet . Results[1] = IoErr();
  741.                         }
  742.  
  743.                             /* Free parser data. */
  744.  
  745.                         if(!Processed)
  746.                             FreeDosObject(DOS_RDARGS,Args);
  747.                     }
  748.                     else
  749.                     {
  750.                         Packet . Results[0] = RC_ERROR;
  751.                         Packet . Results[1] = ERROR_NO_FREE_STORE;
  752.                     }
  753.  
  754.                         /* Free temporary buffer. */
  755.  
  756.                     if(!Processed)
  757.                         FreeVecPooled(Array);
  758.                 }
  759.                 else
  760.                 {
  761.                     Packet . Results[0] = RC_ERROR;
  762.                     Packet . Results[1] = ERROR_NO_FREE_STORE;
  763.                 }
  764.             }
  765.             else
  766.             {
  767.                 Packet . Array    = NULL;
  768.                 Packet . Args    = NULL;
  769.  
  770.                 Processed = InvokeRexxCommand(&Packet);
  771.             }
  772.  
  773.             if(!Processed)
  774.             {
  775.                 if(Packet . Results[0] && Packet . Results[1])
  776.                     LastRexxError = Packet . Results[1];
  777.  
  778.                 ReplyRexxCommand(RexxMsg,Packet . Results[0],Packet . Results[1]);
  779.             }
  780.  
  781.             return(TRUE);
  782.         }
  783.     }
  784.  
  785.     return(FALSE);
  786. }
  787.  
  788.     /* RexxPktCleanup(struct RexxPkt *Packet,STRPTR Result):
  789.      *
  790.      *    Free the memory allocated for a message packet.
  791.      */
  792.  
  793. VOID
  794. RexxPktCleanup(struct RexxPkt *Packet,STRPTR Result)
  795. {
  796.     if(Packet -> Args)
  797.     {
  798.         FreeArgs(Packet -> Args);
  799.  
  800.         FreeDosObject(DOS_RDARGS,Packet -> Args);
  801.     }
  802.  
  803.     FreeVecPooled(Packet -> Array);
  804.  
  805.     if(Packet -> Results[0])
  806.     {
  807.             /* Store error code. */
  808.  
  809.         if(Packet -> Results[1])
  810.         {
  811.             UBYTE Buffer[10];
  812.  
  813.             SPrintf(Buffer,"%ld",LastRexxError = Packet -> Results[1]);
  814.  
  815.             if(Packet -> RexxMsg)
  816.                 SetRexxVar(Packet -> RexxMsg,"TERM.LASTERROR",Buffer,strlen(Buffer));
  817.         }
  818.  
  819.         ReplyRexxCommand(Packet -> RexxMsg,Packet -> Results[0],Packet -> Results[1]);
  820.  
  821.         if(Result)
  822.             DeleteArgstring(Result);
  823.     }
  824.     else
  825.     {
  826.         if(Result)
  827.         {
  828.             if(Packet -> RexxMsg)
  829.             {
  830.                 if(Packet -> RexxMsg -> rm_Action & RXFF_RESULT)
  831.                     ReplyRexxCommand(Packet -> RexxMsg,0,(LONG)Result);
  832.                 else
  833.                 {
  834.                     DeleteArgstring(Result);
  835.  
  836.                     ReplyRexxCommand(Packet -> RexxMsg,0,0);
  837.                 }
  838.             }
  839.             else
  840.                 DeleteArgstring(Result);
  841.         }
  842.         else
  843.             ReplyRexxCommand(Packet -> RexxMsg,0,0);
  844.     }
  845. }
  846.  
  847.     /* RexxServer(VOID):
  848.      *
  849.      *    Asynchronous ARexx host server.
  850.      */
  851.  
  852. VOID __saveds
  853. RexxServer(VOID)
  854. {
  855.         /* Create the public host port. */
  856.  
  857.     if(RexxPort = CreateMsgPort())
  858.     {
  859.         struct RexxMsg    *RexxMsg;
  860.         ULONG         SignalSet;
  861.         BOOL         Done = FALSE;
  862.  
  863.         InitSemaphore(&RexxLaunchSemaphore);
  864.  
  865.         RexxPort -> mp_Node . ln_Name    = RexxPortName;
  866.         RexxPort -> mp_Node . ln_Pri    = 1;
  867.  
  868.             /* Make it a public port. */
  869.  
  870.         AddPort(RexxPort);
  871.  
  872.             /* Signal our father that we're running. */
  873.  
  874.         Signal(ThisProcess,SIG_HANDSHAKE);
  875.  
  876.             /* Go into loop and wait for input. */
  877.  
  878.         do
  879.         {
  880.             SignalSet = Wait(SIG_KILL | PORTMASK(RexxPort));
  881.  
  882.                 /* Are we to quit? */
  883.  
  884.             if(SignalSet & SIG_KILL)
  885.                 Done = TRUE;
  886.  
  887.                 /* This is probably a Rexx command. */
  888.  
  889.             if(SignalSet & PORTMASK(RexxPort))
  890.             {
  891.                     /* Pick up all the messages. */
  892.  
  893.                 while(RexxMsg = (struct RexxMsg *)GetMsg(RexxPort))
  894.                 {
  895.                         /* This is probably the reply to some
  896.                          * synchronous function invocation.
  897.                          */
  898.  
  899.                     if(RexxMsg -> rm_Node . mn_Node . ln_Type == NT_REPLYMSG)
  900.                         FreeVecPooled(RexxMsg);
  901.                     else
  902.                     {
  903.                             /* At first try to run the
  904.                              * command asynchronously.
  905.                              * If this turns out to be
  906.                              * somewhat `impossible' pass
  907.                              * it to the `term' main process
  908.                              * or - if in batch mode - try
  909.                              * to deal with the message
  910.                              * on our own.
  911.                              */
  912.  
  913.                         if(!ParseRexxCommand(RexxMsg))
  914.                         {
  915.                             UBYTE Buffer[10];
  916.  
  917.                             SPrintf(Buffer,"%ld",LastRexxError = TERMERROR_UNKNOWN_COMMAND);
  918.  
  919.                             SetRexxVar(RexxMsg,"TERM.LASTERROR",Buffer,strlen(Buffer));
  920.  
  921.                             ReplyRexxCommand(RexxMsg,RC_ERROR,TERMERROR_UNKNOWN_COMMAND);
  922.                         }
  923.                     }
  924.                 }
  925.             }
  926.         }
  927.         while(!Done);
  928.  
  929.         Done = FALSE;
  930.  
  931.             /* Process remaining messages. */
  932.  
  933.         do
  934.         {
  935.             while(RexxMsg = (struct RexxMsg *)GetMsg(RexxPort))
  936.             {
  937.                 if(RexxMsg -> rm_Node . mn_Node . ln_Type == NT_REPLYMSG)
  938.                     FreeVecPooled(RexxMsg);
  939.                 else
  940.                     ReplyRexxCommand(RexxMsg,-1,0);
  941.             }
  942.  
  943.             ObtainSemaphore(&RexxLaunchSemaphore);
  944.  
  945.             if(!RexxLaunchCount)
  946.             {
  947.                 Done = TRUE;
  948.  
  949.                 ReleaseSemaphore(&RexxLaunchSemaphore);
  950.             }
  951.             else
  952.             {
  953.                 ReleaseSemaphore(&RexxLaunchSemaphore);
  954.  
  955.                 WaitPort(RexxPort);
  956.             }
  957.         }
  958.         while(!Done);
  959.  
  960.         DeleteMsgPort(RexxPort);
  961.  
  962.         RexxPort = NULL;
  963.     }
  964.  
  965.     Forbid();
  966.  
  967.     RexxProcess = NULL;
  968.  
  969.     Signal(ThisProcess,SIG_HANDSHAKE);
  970. }
  971.  
  972.     /* HandleRexx():
  973.      *
  974.      *    Tiny & simple subroutine to read and examine all
  975.      *    messages coming in to be processed synchronously
  976.      *    by the `term' main process.
  977.      */
  978.  
  979. BOOL
  980. HandleRexx()
  981. {
  982.     struct RexxPkt *Packet;
  983.  
  984.         /* Obtain the message packet. */
  985.  
  986.     if(Packet = (struct RexxPkt *)GetMsg(TermRexxPort))
  987.     {
  988.         STRPTR Result;
  989.  
  990.         InRexx = TRUE;
  991.  
  992.         UpdateRequired = TransferUpdateRequired = FALSE;
  993.  
  994.             /* Execute the command. */
  995.  
  996.         Result = (*Packet -> CommandInfo -> Routine)(Packet);
  997.  
  998.             /* Free the packet data. */
  999.  
  1000.         RexxPktCleanup(Packet,Result);
  1001.  
  1002.             /* Update the configuration if necessary. */
  1003.  
  1004.         if(UpdateRequired)
  1005.             ConfigSetup();
  1006.  
  1007.             /* Update the XPR options if necessary. */
  1008.  
  1009.         if(TransferUpdateRequired)
  1010.         {
  1011.             if(ProtocolSetup(TRUE))
  1012.                 SaveProtocolOpts();
  1013.         }
  1014.  
  1015.             /* Return the message packet. */
  1016.  
  1017.         ReplyMsg((struct Message *)Packet);
  1018.  
  1019.         InRexx = FALSE;
  1020.  
  1021.         return(TRUE);
  1022.     }
  1023.     else
  1024.         return(FALSE);
  1025. }
  1026.