home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d8xx / d832 / term.lha / Term / term-3.1-Source.lha / termARexx.c < prev    next >
C/C++ Source or Header  |  1993-02-05  |  18KB  |  1,017 lines

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