home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term33so.lha / termARexx.c < prev    next >
C/C++ Source or Header  |  1993-04-30  |  18KB  |  1,027 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.         "SOUND",
  214.         "BUFFER",
  215.         "CONFIGURATION",
  216.         "PHONE",
  217.         "SCREENTEXT",
  218.         "SCREENIMAGE"
  219.     };
  220.  
  221.     WORD i;
  222.  
  223.     for(i = 0 ; i < DATATYPE_COUNT ; i++)
  224.     {
  225.         if(!Stricmp(Name,DataTypes[i]))
  226.             return(i);
  227.     }
  228.  
  229.     return(-1);
  230. }
  231.  
  232.     /* ToRequester(STRPTR Name):
  233.      *
  234.      *    Turn a requester name into a key.
  235.      */
  236.  
  237. WORD __regargs
  238. ToRequester(STRPTR Name)
  239. {
  240.     STRPTR RequesterTypes[REQUESTER_COUNT] =
  241.     {
  242.         "SERIAL",
  243.         "MODEM",
  244.         "SCREEN",
  245.         "TERMINAL",
  246.         "EMULATION",
  247.         "CLIPBOARD",
  248.         "CAPTURE",
  249.         "COMMANDS",
  250.         "MISC",
  251.         "PATH",
  252.         "TRANSFER",
  253.         "TRANSLATIONS",
  254.         "FUNCTIONKEYS",
  255.         "CURSORKEYS",
  256.         "FASTMACROS",
  257.         "HOTKEYS",
  258.         "SPEECH",
  259.         "SOUND",
  260.         "PHONE"
  261.     };
  262.  
  263.     WORD i;
  264.  
  265.     for(i = 0 ; i < REQUESTER_COUNT ; i++)
  266.     {
  267.         if(!Stricmp(Name,RequesterTypes[i]))
  268.             return(i);
  269.     }
  270.  
  271.     return(-1);
  272. }
  273.  
  274.     /* ToWindow(STRPTR Name):
  275.      *
  276.      *    Turn a window name into a key.
  277.      */
  278.  
  279. WORD __regargs
  280. ToWindow(STRPTR Name)
  281. {
  282.     STATIC STRPTR WindowTypes[WINDOW_COUNT] =
  283.     {
  284.         "BUFFER",
  285.         "REVIEW",
  286.         "PACKET",
  287.         "FASTMACROS",
  288.         "STATUS",
  289.         "MAIN"
  290.     };
  291.  
  292.     WORD i;
  293.  
  294.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  295.     {
  296.         if(!Stricmp(WindowTypes[i],Name))
  297.             return(i);
  298.     }
  299.  
  300.     return(-1);
  301. }
  302.  
  303.     /* ReplyRexxCommand():
  304.      *
  305.      *    Reply a command request the rexx server - or someone else -
  306.      *    has passed to us.
  307.      */
  308.  
  309. STATIC VOID __regargs
  310. ReplyRexxCommand(struct RexxMsg *RexxMessage,LONG Primary,LONG Secondary)
  311. {
  312.     RexxMessage -> rm_Result1 = Primary;
  313.     RexxMessage -> rm_Result2 = Secondary;
  314.  
  315.     ReplyMsg(RexxMessage);
  316. }
  317.  
  318.     /* RexxToolServer(VOID):
  319.      *
  320.      *    Asynchronous tool/rexx command execution process.
  321.      */
  322.  
  323. STATIC VOID __saveds
  324. RexxToolServer(VOID)
  325. {
  326.     struct Process    *ThisProcess = (struct Process *)SysBase -> ThisTask;
  327.     struct RexxPkt    *Packet;
  328.     BPTR         OldCOS,
  329.              NewCOS    = NULL;
  330.  
  331.         /* Wait for startup packet. */
  332.  
  333.     WaitPort(&ThisProcess -> pr_MsgPort);
  334.  
  335.     Packet = (struct RexxPkt *)GetMsg(&ThisProcess -> pr_MsgPort);
  336.  
  337.         /* Increment usage count. */
  338.  
  339.     ObtainSemaphore(&RexxLaunchSemaphore);
  340.  
  341.     RexxLaunchCount++;
  342.  
  343.     ReleaseSemaphore(&RexxLaunchSemaphore);
  344.  
  345.         /* Create proper output stream if necessary. */
  346.  
  347.     if(!ThisProcess -> pr_COS && ThisProcess -> pr_ConsoleTask)
  348.     {
  349.         if(NewCOS = Open("*",MODE_NEWFILE))
  350.         {
  351.             OldCOS = ThisProcess -> pr_COS;
  352.  
  353.             ThisProcess -> pr_COS = NewCOS;
  354.         }
  355.     }
  356.  
  357.         /* Execute the command. */
  358.  
  359.     (*Packet -> CommandInfo -> Routine)(Packet);
  360.  
  361.     Forbid();
  362.  
  363.         /* Decrement usage count. */
  364.  
  365.     ObtainSemaphore(&RexxLaunchSemaphore);
  366.  
  367.     RexxLaunchCount--;
  368.  
  369.     ReleaseSemaphore(&RexxLaunchSemaphore);
  370.  
  371.         /* Close the output stream. */
  372.  
  373.     if(NewCOS)
  374.     {
  375.         ThisProcess -> pr_COS = OldCOS;
  376.  
  377.         Close(NewCOS);
  378.     }
  379.  
  380.         /* Return the message packet. */
  381.  
  382.     ReplyMsg((struct Message *)Packet);
  383. }
  384.  
  385.     /* InvokeRexxCommand(struct RexxPkt *Packet):
  386.      *
  387.      *    Invoke an ARexx command.
  388.      */
  389.  
  390. STATIC BYTE __regargs
  391. InvokeRexxCommand(struct RexxPkt *Packet)
  392. {
  393.         /* Asynchronous command? */
  394.  
  395.     if(Packet -> CommandInfo -> Async)
  396.     {
  397.             /* Requires special execution code? */
  398.  
  399.         if(Packet -> CommandInfo -> Tool)
  400.         {
  401.             struct RexxPkt *NewPacket;
  402.  
  403.                 /* Create a command packet. */
  404.  
  405.             if(NewPacket = (struct RexxPkt *)AllocVec(sizeof(struct RexxPkt),MEMF_ANY | MEMF_PUBLIC))
  406.             {
  407.                 enum    {    ARG_CONSOLE };
  408.  
  409.                 struct Process    *NewProcess;
  410.                 BPTR         Stream;
  411.  
  412.                     /* Set up the command packet. */
  413.  
  414.                 CopyMem(Packet,NewPacket,sizeof(struct RexxPkt));
  415.  
  416.                 NewPacket -> VanillaMessage . mn_ReplyPort    = RexxPort;
  417.                 NewPacket -> VanillaMessage . mn_Length        = sizeof(struct RexxPkt);
  418.  
  419.                     /* Create I/O streams. */
  420.  
  421.                 if(Packet -> Array[ARG_CONSOLE] && WindowName[0] && Packet -> CommandInfo -> Console)
  422.                     Stream = Open(WindowName,MODE_NEWFILE);
  423.                 else
  424.                     Stream = NULL;
  425.  
  426.                     /* Launch the process. */
  427.  
  428.                 if(Stream && GoodStream(Stream))
  429.                 {
  430.                     struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  431.  
  432.                     NewProcess = CreateNewProcTags(
  433.                         NP_Entry,    RexxToolServer,
  434.                         NP_Input,    Stream,
  435.                         NP_Output,    NULL,
  436.                         NP_ConsoleTask,    Handle -> fh_Type,
  437.                         NP_StackSize,    8000,
  438.                         NP_Name,    "term Rexx tool process",
  439.                         NP_Cli,        TRUE,
  440.                     TAG_DONE);
  441.                 }
  442.                 else
  443.                 {
  444.                     NewProcess = CreateNewProcTags(
  445.                         NP_Entry,    RexxToolServer,
  446.                         NP_StackSize,    8000,
  447.                         NP_ConsoleTask,    NULL,
  448.                         NP_Name,    "term Rexx tool process",
  449.                         NP_Cli,        TRUE,
  450.                     TAG_DONE);
  451.                 }
  452.  
  453.                     /* Send the command packet. */
  454.  
  455.                 if(NewProcess)
  456.                     PutMsg(&NewProcess -> pr_MsgPort,(struct Message *)NewPacket);
  457.                 else
  458.                 {
  459.                     FreeVec(NewPacket);
  460.  
  461.                     ReplyRexxCommand(Packet -> RexxMsg,-1,0);
  462.  
  463.                     if(Stream)
  464.                         Close(Stream);
  465.                 }
  466.             }
  467.             else
  468.                 ReplyRexxCommand(Packet -> RexxMsg,-1,0);
  469.         }
  470.         else
  471.         {
  472.                 /* Execute the command on the schedule of the
  473.                  * rexx server process.
  474.                  */
  475.  
  476.             STRPTR Result = (*Packet -> CommandInfo -> Routine)(Packet);
  477.  
  478.             RexxPktCleanup(Packet,Result);
  479.         }
  480.     }
  481.     else
  482.     {
  483.         struct RexxPkt *NewPacket;
  484.  
  485.             /* Create message packet. */
  486.  
  487.         if(NewPacket = (struct RexxPkt *)AllocVec(sizeof(struct RexxPkt),MEMF_ANY | MEMF_PUBLIC))
  488.         {
  489.                 /* Set up message packet. */
  490.  
  491.             CopyMem(Packet,NewPacket,sizeof(struct RexxPkt));
  492.  
  493.             NewPacket -> VanillaMessage . mn_ReplyPort    = RexxPort;
  494.             NewPacket -> VanillaMessage . mn_Length        = sizeof(struct RexxPkt);
  495.  
  496.                 /* Post it. */
  497.  
  498.             PutMsg(TermRexxPort,(struct Message *)NewPacket);
  499.         }
  500.         else
  501.             ReplyRexxCommand(Packet -> RexxMsg,-1,0);
  502.     }
  503.  
  504.     return(TRUE);
  505. }
  506.  
  507.     /* ParseRexxCommand(struct RexxMsg *RexxMsg):
  508.      *
  509.      *    Handles the synchronous Rexx commands and returns the
  510.      *    message if no matching command is found.
  511.      */
  512.  
  513. STATIC BYTE
  514. ParseRexxCommand(struct RexxMsg *RexxMsg)
  515. {
  516.     UBYTE    CommandBuffer[30];
  517.     STRPTR    Command,
  518.         CommandArgs;
  519.     LONG    Len = 0;
  520.  
  521.         /* Clear the local variables. */
  522.  
  523.     CommandBuffer[0]    = 0;
  524.     Command            = RexxMsg -> rm_Args[0];
  525.     CommandArgs        = NULL;
  526.  
  527.         /* Skip leading blank spaces. */
  528.  
  529.     while(*Command && (*Command == ' ' || *Command == '\t'))
  530.         Command++;
  531.  
  532.         /* Extract the command name. */
  533.  
  534.     do
  535.     {
  536.             /* Found the end of the string? */
  537.  
  538.         if(!Command[Len])
  539.         {
  540.                 /* Copy the command name. */
  541.  
  542.             strcpy(CommandBuffer,Command);
  543.  
  544.                 /* No arguments are provided. */
  545.  
  546.             CommandArgs = NULL;
  547.  
  548.             break;
  549.         }
  550.  
  551.             /* Found a blank space? */
  552.  
  553.         if(Command[Len] == ' ' || Command[Len] == '\t')
  554.         {
  555.                 /* Copy the command name. */
  556.  
  557.             memcpy(CommandBuffer,Command,Len);
  558.  
  559.             CommandBuffer[Len] = 0;
  560.  
  561.                 /* Look for any arguments. */
  562.  
  563.             CommandArgs = &Command[Len + 1];
  564.  
  565.                 /* Skip blank spaces. */
  566.  
  567.             while(*CommandArgs && (*CommandArgs == ' ' || *CommandArgs == '\t'))
  568.                 CommandArgs++;
  569.  
  570.             break;
  571.         }
  572.     }
  573.     while(++Len < 30);
  574.  
  575.         /* Did we find a command name? */
  576.  
  577.     if(CommandBuffer[0])
  578.     {
  579.         struct CommandInfo    *CommandInfo = NULL;
  580.         LONG             CommandIndex;
  581.  
  582.             /* Which command is it? */
  583.  
  584.         for(CommandIndex = 0 ; CommandIndex < CommandTableSize ; CommandIndex++)
  585.         {
  586.             if(!Stricmp(CommandBuffer,CommandTable[CommandIndex] . Name))
  587.             {
  588.                 CommandInfo = &CommandTable[CommandIndex];
  589.  
  590.                 break;
  591.             }
  592.         }
  593.  
  594.             /* Did we find the command? */
  595.  
  596.         if(CommandInfo)
  597.         {
  598.             struct RexxPkt __aligned    Packet;
  599.             BYTE                Processed = FALSE;
  600.  
  601.                 /* Set the result codes to defaults. */
  602.  
  603.             Packet . Results[0]    = RC_OK;
  604.             Packet . Results[1]    = 0;
  605.  
  606.                 /* Fill in the rest. */
  607.  
  608.             Packet . CommandInfo    = CommandInfo;
  609.             Packet . RexxMsg    = RexxMsg;
  610.  
  611.                 /* Does this command accept any arguments? */
  612.  
  613.             if(CommandInfo -> Arguments)
  614.             {
  615.                 LONG *Array;
  616.  
  617.                     /* Determine length of argument string. */
  618.  
  619.                 if(CommandArgs)
  620.                     Len = strlen(CommandArgs);
  621.                 else
  622.                     Len = 0;
  623.  
  624.                     /* Allocate temporary buffer, we will need to
  625.                      * attach a line-feed character to the argument
  626.                      * string.
  627.                      */
  628.  
  629.                 if(Array = (LONG *)AllocVec(12 * sizeof(LONG) + Len + 2,MEMF_ANY | MEMF_CLEAR | MEMF_PUBLIC))
  630.                 {
  631.                     STRPTR         Buffer;
  632.                     struct RDArgs    *Args;
  633.  
  634.                         /* Get the argument buffer. */
  635.  
  636.                     Buffer = (STRPTR)&Array[12];
  637.  
  638.                         /* Copy the argument string. */
  639.  
  640.                     if(CommandArgs && Len)
  641.                         memcpy(Buffer,CommandArgs,Len);
  642.  
  643.                         /* Attach the line-feed character. */
  644.  
  645.                     Buffer[Len] = '\n';
  646.  
  647.                         /* Allocate argument parser data. */
  648.  
  649.                     if(Args = (struct RDArgs *)AllocDosObjectTags(DOS_RDARGS,TAG_DONE))
  650.                     {
  651.                         Packet . Array    = (STRPTR *)Array;
  652.                         Packet . Args    = Args;
  653.  
  654.                             /* Don't prompt for input! */
  655.  
  656.                         Args -> RDA_Flags |= RDAF_NOPROMPT;
  657.  
  658.                             /* Set up parser data. */
  659.  
  660.                         Args -> RDA_Source . CS_Buffer    = Buffer;
  661.                         Args -> RDA_Source . CS_Length    = Len + 1;
  662.                         Args -> RDA_Source . CS_CurChr    = 0;
  663.  
  664.                             /* Parse the arguments. */
  665.  
  666.                         if(ReadArgs(CommandInfo -> Arguments,Array,Args))
  667.                         {
  668.                             UWORD    Inclusion    = InclusionTable[CommandIndex];
  669.                             BYTE    ArgsRequired    = FALSE;
  670.                             WORD    i,Counted;
  671.  
  672.                                 /* Look for required arguments. */
  673.  
  674.                             for(i = Counted = 0 ; i < 12 ; i++)
  675.                             {
  676.                                 if(Inclusion & (1 << i))
  677.                                 {
  678.                                     ArgsRequired = TRUE;
  679.  
  680.                                     if(Array[i])
  681.                                         Counted++;
  682.                                 }
  683.                             }
  684.  
  685.                                 /* Are any arguments required
  686.                                  * but not provided?
  687.                                  */
  688.  
  689.                             if(ArgsRequired && !Counted)
  690.                             {
  691.                                 Packet . Results[0] = RC_ERROR;
  692.                                 Packet . Results[1] = ERROR_REQUIRED_ARG_MISSING;
  693.                             }
  694.                             else
  695.                             {
  696.                                 struct ExclusionInfo *Exclusion = ExclusionTable[CommandIndex];
  697.  
  698.                                     /* Any mutually-exclusive arguments? */
  699.  
  700.                                 if(Exclusion)
  701.                                 {
  702.                                     BYTE ArgsOkay = TRUE;
  703.  
  704.                                     i = 0;
  705.  
  706.                                         /* Look for arguments to
  707.                                          * exclude each other.
  708.                                          */
  709.  
  710.                                     while(ArgsOkay && Exclusion[i] . A != -1)
  711.                                     {
  712.                                         if(Array[Exclusion[i] . A] && Array[Exclusion[i] . B])
  713.                                             ArgsOkay = FALSE;
  714.                                         else
  715.                                             i++;
  716.                                     }
  717.  
  718.                                         /* All arguments correct? */
  719.  
  720.                                     if(ArgsOkay)
  721.                                         Processed = InvokeRexxCommand(&Packet);
  722.                                     else
  723.                                     {
  724.                                         Packet . Results[0] = RC_ERROR;
  725.                                         Packet . Results[1] = ERROR_TOO_MANY_ARGS;
  726.                                     }
  727.                                 }
  728.                                 else
  729.                                     Processed = InvokeRexxCommand(&Packet);
  730.                             }
  731.  
  732.                                 /* Free allocated parser data. */
  733.  
  734.                             if(!Processed)
  735.                                 FreeArgs(Args);
  736.                         }
  737.                         else
  738.                         {
  739.                             LONG Error = IoErr();
  740.  
  741.                             SetIoErr(Error);
  742.  
  743.                             Packet . Results[0] = RC_ERROR;
  744.                             Packet . Results[1] = IoErr();
  745.                         }
  746.  
  747.                             /* Free parser data. */
  748.  
  749.                         if(!Processed)
  750.                             FreeDosObject(DOS_RDARGS,Args);
  751.                     }
  752.                     else
  753.                     {
  754.                         Packet . Results[0] = RC_ERROR;
  755.                         Packet . Results[1] = ERROR_NO_FREE_STORE;
  756.                     }
  757.  
  758.                         /* Free temporary buffer. */
  759.  
  760.                     if(!Processed)
  761.                         FreeVec(Array);
  762.                 }
  763.                 else
  764.                 {
  765.                     Packet . Results[0] = RC_ERROR;
  766.                     Packet . Results[1] = ERROR_NO_FREE_STORE;
  767.                 }
  768.             }
  769.             else
  770.             {
  771.                 Packet . Array    = NULL;
  772.                 Packet . Args    = NULL;
  773.  
  774.                 Processed = InvokeRexxCommand(&Packet);
  775.             }
  776.  
  777.             if(!Processed)
  778.             {
  779.                 if(Packet . Results[0] && Packet . Results[1])
  780.                     LastRexxError = Packet . Results[1];
  781.  
  782.                 ReplyRexxCommand(RexxMsg,Packet . Results[0],Packet . Results[1]);
  783.             }
  784.  
  785.             return(TRUE);
  786.         }
  787.     }
  788.  
  789.     return(FALSE);
  790. }
  791.  
  792.     /* RexxPktCleanup(struct RexxPkt *Packet,STRPTR Result):
  793.      *
  794.      *    Free the memory allocated for a message packet.
  795.      */
  796.  
  797. VOID __regargs
  798. RexxPktCleanup(struct RexxPkt *Packet,STRPTR Result)
  799. {
  800.     if(Packet -> Args)
  801.     {
  802.         FreeArgs(Packet -> Args);
  803.  
  804.         FreeDosObject(DOS_RDARGS,Packet -> Args);
  805.     }
  806.  
  807.     if(Packet -> Array)
  808.         FreeVec(Packet -> Array);
  809.  
  810.     if(Packet -> Results[0])
  811.     {
  812.             /* Store error code. */
  813.  
  814.         if(Packet -> Results[1])
  815.         {
  816.             UBYTE Buffer[10];
  817.  
  818.             SPrintf(Buffer,"%ld",LastRexxError = Packet -> Results[1]);
  819.  
  820.             SetRexxVar(Packet -> RexxMsg,"TERM.LASTERROR",Buffer,strlen(Buffer));
  821.         }
  822.  
  823.         ReplyRexxCommand(Packet -> RexxMsg,Packet -> Results[0],Packet -> Results[1]);
  824.  
  825.         if(Result)
  826.             DeleteArgstring(Result);
  827.     }
  828.     else
  829.     {
  830.         if(Result)
  831.         {
  832.             if(Packet -> RexxMsg -> rm_Action & RXFF_RESULT)
  833.                 ReplyRexxCommand(Packet -> RexxMsg,0,(LONG)Result);
  834.             else
  835.             {
  836.                 DeleteArgstring(Result);
  837.  
  838.                 ReplyRexxCommand(Packet -> RexxMsg,0,0);
  839.             }
  840.         }
  841.         else
  842.             ReplyRexxCommand(Packet -> RexxMsg,0,0);
  843.     }
  844. }
  845.  
  846.     /* RexxServer(VOID):
  847.      *
  848.      *    Asynchronous ARexx host server.
  849.      */
  850.  
  851. VOID __saveds
  852. RexxServer(VOID)
  853. {
  854.         /* Create the public host port. */
  855.  
  856.     if(RexxPort = CreateMsgPort())
  857.     {
  858.         struct RexxMsg    *RexxMsg;
  859.         ULONG         SignalSet;
  860.         BYTE         Done = FALSE;
  861.     
  862.         InitSemaphore(&RexxLaunchSemaphore);
  863.  
  864.         RexxPort -> mp_Node . ln_Name    = RexxPortName;
  865.         RexxPort -> mp_Node . ln_Pri    = 1;
  866.  
  867.             /* Make it a public port. */
  868.  
  869.         AddPort(RexxPort);
  870.  
  871.             /* Signal our father that we're running. */
  872.  
  873.         Signal(ThisProcess,SIG_HANDSHAKE);
  874.  
  875.             /* Go into loop and wait for input. */
  876.  
  877.         do
  878.         {
  879.             SignalSet = Wait(SIG_KILL | PORTMASK(RexxPort));
  880.  
  881.                 /* Are we to quit? */
  882.  
  883.             if(SignalSet & SIG_KILL)
  884.                 Done = TRUE;
  885.  
  886.                 /* This is probably a Rexx command. */
  887.  
  888.             if(SignalSet & PORTMASK(RexxPort))
  889.             {
  890.                     /* Pick up all the messages. */
  891.  
  892.                 while(RexxMsg = (struct RexxMsg *)GetMsg(RexxPort))
  893.                 {
  894.                     if(IsRexxMsg(RexxMsg))
  895.                     {
  896.                             /* At first try to run the
  897.                              * command asynchronously.
  898.                              * If this turns out to be
  899.                              * somewhat `impossible' pass
  900.                              * it to the `term' main process
  901.                              * or - if in batch mode - try
  902.                              * to deal with the message
  903.                              * on our own.
  904.                              */
  905.  
  906.                         if(!ParseRexxCommand(RexxMsg))
  907.                         {
  908.                             UBYTE Buffer[10];
  909.  
  910.                             SPrintf(Buffer,"%ld",LastRexxError = TERMERROR_UNKNOWN_COMMAND);
  911.  
  912.                             SetRexxVar(RexxMsg,"TERM.LASTERROR",Buffer,strlen(Buffer));
  913.  
  914.                             ReplyRexxCommand(RexxMsg,RC_ERROR,TERMERROR_UNKNOWN_COMMAND);
  915.                         }
  916.                     }
  917.                     else
  918.                     {
  919.                             /* This is probably the reply to some
  920.                              * synchronous function invocation.
  921.                              */
  922.  
  923.                         FreeVec(RexxMsg);
  924.                     }
  925.                 }
  926.             }
  927.         }
  928.         while(!Done);
  929.     
  930.         Done = FALSE;
  931.  
  932.             /* Process remaining messages. */
  933.  
  934.         do
  935.         {
  936.             while(RexxMsg = (struct RexxMsg *)GetMsg(RexxPort))
  937.             {
  938.                 if(IsRexxMsg(RexxMsg))
  939.                     ReplyRexxCommand(RexxMsg,-1,0);
  940.                 else
  941.                     FreeVec(RexxMsg);
  942.             }
  943.  
  944.             ObtainSemaphore(&RexxLaunchSemaphore);
  945.  
  946.             if(!RexxLaunchCount)
  947.             {
  948.                 Done = TRUE;
  949.  
  950.                 ReleaseSemaphore(&RexxLaunchSemaphore);
  951.             }
  952.             else
  953.             {
  954.                 ReleaseSemaphore(&RexxLaunchSemaphore);
  955.  
  956.                 WaitPort(RexxPort);
  957.             }
  958.         }
  959.         while(!Done);
  960.  
  961.         DeleteMsgPort(RexxPort);
  962.  
  963.         RexxPort = NULL;
  964.     }
  965.  
  966.     Forbid();
  967.  
  968.     RexxProcess = NULL;
  969.  
  970.     Signal(ThisProcess,SIG_HANDSHAKE);
  971. }
  972.  
  973.     /* HandleRexx():
  974.      *
  975.      *    Tiny & simple subroutine to read and examine all
  976.      *    messages coming in to be processed synchronously
  977.      *    by the `term' main process.
  978.      */
  979.  
  980. BYTE
  981. HandleRexx()
  982. {
  983.     struct RexxPkt *Packet;
  984.  
  985.         /* Obtain the message packet. */
  986.  
  987.     if(Packet = (struct RexxPkt *)GetMsg(TermRexxPort))
  988.     {
  989.         STRPTR Result;
  990.  
  991.         InRexx = TRUE;
  992.  
  993.         UpdateRequired = TransferUpdateRequired = FALSE;
  994.  
  995.             /* Execute the command. */
  996.  
  997.         Result = (*Packet -> CommandInfo -> Routine)(Packet);
  998.  
  999.             /* Free the packet data. */
  1000.  
  1001.         RexxPktCleanup(Packet,Result);
  1002.  
  1003.             /* Update the configuration if necessary. */
  1004.  
  1005.         if(UpdateRequired)
  1006.             ConfigSetup();
  1007.  
  1008.             /* Update the XPR options if necessary. */
  1009.  
  1010.         if(TransferUpdateRequired)
  1011.         {
  1012.             if(ProtocolSetup(TRUE))
  1013.                 SaveProtocolOpts();
  1014.         }
  1015.  
  1016.             /* Return the message packet. */
  1017.  
  1018.         ReplyMsg((struct Message *)Packet);
  1019.  
  1020.         InRexx = FALSE;
  1021.  
  1022.         return(TRUE);
  1023.     }
  1024.     else
  1025.         return(FALSE);
  1026. }
  1027.