home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #3 / amigamamagazinepolishissue1998.iso / szachy / gnu / amyboard-3.2.pl2 / amiga / childio.c < prev    next >
C/C++ Source or Header  |  1995-05-23  |  32KB  |  1,314 lines

  1. /**
  2. ***  childio.c  -- Internal pipe for child process communications
  3. ***
  4. *** ------------------------------------------------------------------------
  5. ***  This program is free software; you can redistribute it and/or modify
  6. ***  it under the terms of the GNU General Public License as published by
  7. ***  the Free Software Foundation; either version 2 of the License, or
  8. ***  (at your option) any later version.
  9. ***
  10. ***  This program is distributed in the hope that it will be useful,
  11. ***  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ***  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ***  GNU General Public License for more details.
  14. ***
  15. ***  You should have received a copy of the GNU General Public License
  16. ***  along with this program; if not, write to the Free Software
  17. ***  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. *** ------------------------------------------------------------------------
  19. ***
  20. ***
  21. ***  Process communication is done using a second Process, which acts as a
  22. ***  handler. It would be possible to manage everything with one process,
  23. ***  but the increase of speed is not that much and it simplifies things.
  24. ***  It would as well be possible to use a separate pipe handler, but there
  25. ***  are a few problems:
  26. ***
  27. ***  - Usual pipes ("PIPE:" for example) don't work interactively. The
  28. ***    reading process has to wait until the writing process closes the
  29. ***    file.
  30. ***  - The first point could be solved by writing an own handler which
  31. ***    would do quite the same as our internal handler. But we would
  32. ***    need a MountList entry and it would not be possible to remove
  33. ***    this handler.
  34. ***
  35. ***  I recommend chapter 21 of Ralph Babel's "Guru book" for a complete
  36. ***  understanding of what's going on here. (And, BTW, thanks, Ralph,
  37. ***  for your explanations at IRC!)
  38. **/
  39.  
  40.  
  41.  
  42.  
  43.  
  44. /***  Includes section
  45. */
  46. #include "amyboard.h"
  47.  
  48. #include <ctype.h>
  49. #include <fcntl.h>
  50.  
  51. #include <exec/memory.h>
  52. #include <dos/dosextens.h>
  53. #include <dos/dostags.h>
  54. #include <rexx/rexxio.h>
  55.  
  56. #if defined(__GNUC__)
  57. extern BPTR *__stdfiledes;
  58. #define fdtofh(a) (__stdfiledes[a])
  59. #endif
  60. /**/
  61.  
  62.  
  63.  
  64.  
  65. /*** Type definitions
  66. */
  67. typedef struct              /*  Our private extension of the MinNode    */
  68. { struct Node *succ;
  69.   struct Node *pred;
  70.   ULONG size;
  71. } MyMinNode;
  72.  
  73. typedef struct              /*  This structure is created for every     */
  74. { MyMinNode node;           /*  filehandle that is waiting for input,   */
  75.   struct DosPacket *dp;     /*  if no input is available yet.           */
  76. } ReadRequest;
  77.  
  78. typedef struct              /*  This structure is created, if a filehandle  */
  79. { MyMinNode node;           /*  wants to write output, but the ReadRequests */
  80.   ULONG numBytes;           /*  available aren't sufficient. numBytes is    */
  81.   ULONG written;            /*  the available number of bytes, written      */
  82.   UBYTE *buffer;            /*  is the number of bytes already written.     */
  83. } WriteRequest;
  84.  
  85. typedef struct              /*  A pointer to this structure is stored in    */
  86. { APTR pipe;                /*  the fh_Arg1 entry of the filehandle.        */
  87. } XBoardFileHandle;
  88.  
  89. typedef struct              /*  This structure implements one pipe.         */
  90. { MyMinNode node;           /*  Note, that always almost one of the two     */
  91.   struct MinList rreqList;  /*  lists is empty.                             */
  92.   struct MinList wreqList;
  93.   XBoardFileHandle *readFH;
  94.   XBoardFileHandle *writeFH;
  95. } XBoardPipe;
  96.  
  97. /**/
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104. /***  Macro section
  105. */
  106. #define RemoveMyMinNode(mmn) \
  107.   { Remove((struct Node *)mmn); \
  108.     LibFreePooled(pipesPool, mmn, (mmn)->size); \
  109.   }
  110. #define CreateMyMinNode(len) LibAllocPooled(pipesPool, (len))
  111. /**/
  112.  
  113.  
  114.  
  115.  
  116. /*** Variable section
  117. */
  118. struct Process *handlerProcess  = NULL;
  119. struct MsgPort *pipesPort       = NULL;
  120. struct DosPacket *pipesPacket   = NULL;
  121. APTR pipesPool                  = NULL;
  122. ULONG pipeSignals;
  123. struct MinList inputSourceList;
  124. struct MinList childProcessList;
  125. /**/
  126.  
  127.  
  128.  
  129.  
  130. /*** xboardPipesHandler function
  131. ***
  132. ***  This is the equivalent to the handlers main. It is
  133. ***  the entry point of the second process and called via
  134. **   CreateNewProc().
  135. **/
  136. #ifdef DEBUG_HANDLER
  137. void kprints(char *buffer, int len)
  138.  
  139. { int i;
  140.  
  141.   kprintf("(%ld bytes, ", len);
  142.   for (i = len;  i;  i--)
  143.   { char c = *buffer++;
  144.  
  145.     switch(c)
  146.     { case '\n':
  147.     kprintf("\\n");
  148.     break;
  149.       case '\0':
  150.     kprintf("\\0");
  151.     break;
  152.       case '\t':
  153.     kprintf("\\t");
  154.     break;
  155.       case '\r':
  156.     kprintf("\\r");
  157.     break;
  158.       default:
  159.     kprintf("%lc", c);
  160.     }
  161.   }
  162.   kprintf(")\n");
  163. }
  164. #endif
  165. extern VOID xboardPipesHandler(VOID);
  166. _SAVEDS_FUNC(VOID, xboardPipesHandler) (VOID)
  167.  
  168. { struct MsgPort *messagePort;
  169.   struct DosPacket *dosPacket;
  170.   struct DosPacket *diePacket = NULL;
  171.   struct MinList xboardPipesList; /*  List of open pipes.             */
  172.   struct Message *currentMessage;
  173.  
  174.   messagePort = &((struct Process *) FindTask(NULL))->pr_MsgPort;
  175.   NewList((struct List *) &xboardPipesList);
  176.  
  177.   /**
  178.   ***  Never ending loop to process the incoming packets.
  179.   **/
  180.   for (;;)
  181.   { WaitPort(messagePort);
  182.     while((currentMessage = GetMsg(messagePort)))
  183.     { dosPacket = (struct DosPacket *) currentMessage->mn_Node.ln_Name;
  184.       switch(dosPacket->dp_Type)
  185.       { case ACTION_FINDINPUT:
  186.     case ACTION_FINDOUTPUT:
  187.     case ACTION_FINDUPDATE:
  188.     { XBoardPipe *xp;
  189.       XBoardFileHandle *xfh;
  190.       struct FileHandle *fh;
  191.  
  192.       /**
  193.       ***  Create a FileHandle.
  194.       **/
  195.       if ((xfh = CreateMyMinNode(sizeof(*xfh)))  ==  NULL)
  196.       { ReplyPkt(dosPacket, DOSFALSE, ERROR_NO_FREE_STORE);
  197. #ifdef DEBUG_HANDLER
  198. #define kprinta(type)                         \
  199.         switch(type)                      \
  200.         { case ACTION_FINDINPUT:          \
  201.         kprintf("ACTION_FINDINPUT");  \
  202.         break;                        \
  203.           case ACTION_FINDOUTPUT:         \
  204.         kprintf("ACTION_FINDOUTPUT"); \
  205.         break;                        \
  206.           case ACTION_FINDUPDATE:         \
  207.         kprintf("ACTION_FINDUPDATE"); \
  208.         break;                        \
  209.         }
  210.         kprintf("Handler: ");
  211.         kprinta(dosPacket->dp_Type);
  212.         kprintf(" failed, memory error");
  213. #endif
  214.         break;
  215.       }
  216.  
  217.       if (dosPacket->dp_Type == ACTION_FINDINPUT)
  218.       { /**
  219.         ***  If it is a read filehandle: Connect it to the last opened
  220.         ***  pipe. This would not make much sense in a public handler,
  221.         ***  but works fine for us.
  222.         **/
  223.         xp = (XBoardPipe *) xboardPipesList.mlh_TailPred;
  224.         xp->readFH = xfh;
  225.       }
  226.       else
  227.       { /**
  228.         ***  If it is a writing filehandle: Create a new pipe.
  229.         **/
  230.         if ((xp = CreateMyMinNode(sizeof(*xp)))  ==  NULL)
  231.         { ReplyPkt(dosPacket, DOSFALSE, ERROR_NO_FREE_STORE);
  232.           LibFreePooled(pipesPool, xfh, sizeof(*xfh));
  233. #ifdef DEBUG_HANDLER
  234.           kprintf("Handler: ");
  235.           kprinta(dosPacket->dp_Type);
  236.           kprintf(" failed, memory error");
  237. #endif
  238.           break;
  239.         }
  240.         xp->node.size = sizeof(*xp);
  241.         xp->writeFH = xfh;
  242.         xp->readFH = NULL;
  243.         AddTail((struct List *) &xboardPipesList, (struct Node *) xp);
  244.         NewList((struct List *) &xp->rreqList);
  245.         NewList((struct List *) &xp->wreqList);
  246.       }
  247.  
  248.       xfh->pipe = xp;
  249.       fh = (struct FileHandle *) BADDR(dosPacket->dp_Arg1);
  250.       fh->fh_Arg1 = (LONG) xfh;
  251.       fh->fh_Port = (struct MsgPort *) DOSTRUE;
  252.       if (dosPacket->dp_Type == ACTION_FINDUPDATE)
  253.       { fh->fh_Type = pipesPort;    /*  Packets will be sent to the */
  254.       }                             /*  XBoard process immediately. */
  255.  
  256.       ReplyPkt(dosPacket, DOSTRUE, 0);
  257.  
  258. #ifdef DEBUG_HANDLER
  259.       kprintf("Handler: ");
  260.       kprinta(dosPacket->dp_Type);
  261.       kprintf(": Pipe %08lx, FileHandle %08lx created.\n",
  262.           xp, xfh);
  263. #endif
  264.       break;
  265.     }
  266.     case ACTION_READ:
  267.     { XBoardPipe *xp;
  268.       XBoardFileHandle *xfh;
  269.       WriteRequest *wreq;
  270.       ReadRequest *rreq;
  271.  
  272.       xfh = (XBoardFileHandle *) dosPacket->dp_Arg1;
  273.       xp = xfh->pipe;
  274.  
  275.       /**
  276.       ***  Fail, if this is not the reading filehandle.
  277.       **/
  278.       if (xfh  !=  xp->readFH)
  279.       {
  280. #ifdef DEBUG_HANDLER
  281.         kprintf("Handler: ACTION_READ, Pipe %08lx, FileHandle %08lx:\n"
  282.             "         Not reading filehandle, failed.\n",
  283.             xp, xfh);
  284. #endif
  285.         ReplyPkt(dosPacket, 0, ERROR_OBJECT_WRONG_TYPE);
  286.         break;
  287.       }
  288.  
  289.       /**
  290.       ***  Check, if a WriteRequest is waiting.
  291.       **/
  292.       wreq = (WriteRequest *) xp->wreqList.mlh_Head;
  293.       if (wreq->node.succ)
  294.       { ULONG bytesToWrite;
  295.  
  296.         bytesToWrite = MIN(wreq->numBytes - wreq->written,
  297.                    dosPacket->dp_Arg3);
  298.         CopyMem(wreq->buffer + wreq->written,
  299.             (void *) dosPacket->dp_Arg2,
  300.             bytesToWrite);
  301. #ifdef DEBUG_HANDLER
  302.         kprintf("Handler: ACTION_READ, Pipe %08lx, FileHandle %08lx:\n"
  303.             "         Wrote from write request %08lx ",
  304.             xp, xfh, wreq);
  305.         kprints((char *) dosPacket->dp_Arg2, bytesToWrite);
  306. #endif
  307.         ReplyPkt(dosPacket, bytesToWrite, 0);
  308.         wreq->written += bytesToWrite;
  309.  
  310.         if (wreq->written  ==  wreq->numBytes)
  311.         { RemoveMyMinNode((MyMinNode *) wreq);
  312.         }
  313.         break;
  314.       }
  315.  
  316.  
  317.       /**
  318.       ***  Return EOF, if the writing filehandle is closed.
  319.       **/
  320.       if (!xp->writeFH)
  321.       {
  322. #ifdef DEBUG_HANDLER
  323.         kprintf("Handler: ACTION_READ, Pipe %08lx, FileHandle %08lx:\n"
  324.             "         Sent EOF.\n",
  325.             xp, xfh);
  326. #endif
  327.         ReplyPkt(dosPacket, 0, 0);
  328.         break;
  329.       }
  330.  
  331.       /**
  332.       ***  Otherwise create a ReadRequest.
  333.       **/
  334.       if ((rreq = CreateMyMinNode(sizeof(*rreq)))  ==  NULL)
  335.       {
  336. #ifdef DEBUG_HANDLER
  337.         kprintf("Handler: ACTION_READ, Pipe %08lx, FileHandle %08lx:\n"
  338.             "         Failed to create read request, memory error.\n",
  339.             xp, xfh);
  340. #endif
  341.         ReplyPkt(dosPacket, 0, ERROR_NO_FREE_STORE);
  342.         break;
  343.       }
  344.       rreq->node.size = sizeof(*rreq);
  345.       rreq->dp = dosPacket;
  346.       AddTail((struct List *) &xp->rreqList, (struct Node *) rreq);
  347. #ifdef DEBUG_HANDLER
  348.       kprintf("Handler: ACTION_READ, Pipe %08lx, FileHandle %08lx:\n"
  349.           "         Created read request %08lx.\n",
  350.           xp, xfh, rreq);
  351. #endif
  352.       break;
  353.     }
  354.     case ACTION_WRITE:
  355.     { XBoardPipe *xp;
  356.       XBoardFileHandle *xfh;
  357.       ReadRequest *rreq;
  358.       ULONG written = 0;
  359.       ULONG toWrite;
  360.  
  361.       xfh = ((XBoardFileHandle *) dosPacket->dp_Arg1);
  362.       xp = xfh->pipe;
  363.       toWrite = dosPacket->dp_Arg3;
  364.  
  365.       /**
  366.       ***  Fail, if this is not the writing filehandle.
  367.       **/
  368.       if (dosPacket->dp_Arg1  !=  (LONG) xp->writeFH)
  369.       {
  370. #ifdef DEBUG_HANDLER
  371.         kprintf("Handler: ACTION_WRITE, Pipe %08lx, FileHandle %08lx:\n"
  372.             "         Not writing filehandle, failed.\n",
  373.             xp, xfh);
  374. #endif
  375.         ReplyPkt(dosPacket, 0, ERROR_OBJECT_WRONG_TYPE);
  376.         break;
  377.       }
  378.  
  379.       /**
  380.       ***  Fail, if the reading filehandle is closed.
  381.       **/
  382.       if (!xp->readFH)
  383.       {
  384. #ifdef DEBUG_HANDLER
  385.         kprintf("Handler: ACTION_WRITE, Pipe %08lx, FileHandle %08lx:\n"
  386.             "         Reading filehandle closed, failed.\n",
  387.             xp, xfh);
  388. #endif
  389.         ReplyPkt(dosPacket, 0, ERROR_OBJECT_NOT_FOUND);
  390.         break;
  391.       }
  392.  
  393.       /**
  394.       ***  Check, if ReadRequests are waiting.
  395.       **/
  396.       while (toWrite > 0  &&
  397.          (rreq = (ReadRequest *) xp->rreqList.mlh_Head)->node.succ)
  398.       { ULONG bytesToWrite;
  399.  
  400.         bytesToWrite = MIN(toWrite, rreq->dp->dp_Arg3);
  401.         CopyMem((STRPTR) dosPacket->dp_Arg2 + written,
  402.             (STRPTR) rreq->dp->dp_Arg2,
  403.             bytesToWrite);
  404.  
  405. #ifdef DEBUG_HANDLER
  406.         kprintf("Handler: ACTION_WRITE, Pipe %08lx, FileHandle %08lx:\n"
  407.             "         Wrote to read request %08lx ",
  408.             xp, xfh, rreq);
  409.         kprints((STRPTR) rreq->dp->dp_Arg2, bytesToWrite);
  410. #endif
  411.         ReplyPkt(rreq->dp, bytesToWrite, 0);
  412.         written += bytesToWrite;
  413.         toWrite -= bytesToWrite;
  414.         RemoveMyMinNode((MyMinNode *) rreq);
  415.       }
  416.  
  417.       /**
  418.       ***   If bytes are still remaining: Create a write request.
  419.       **/
  420.       if (toWrite > 0)
  421.       { WriteRequest *wreq;
  422.  
  423.         if (!(wreq = CreateMyMinNode(sizeof(*wreq) + toWrite)))
  424.         {
  425. #ifdef DEBUG_HANDLER
  426.         kprintf("Handler: ACTION_WRITE, Pipe %08lx, FileHandle %08lx:\n"
  427.             "         Failed to create write request, memory error.\n",
  428.             xp, xfh);
  429. #endif
  430.           ReplyPkt(dosPacket, written, ERROR_NO_FREE_STORE);
  431.           break;
  432.         }
  433.         wreq->node.size = sizeof(*wreq) + toWrite;
  434.         wreq->numBytes = toWrite;
  435.         wreq->buffer = ((UBYTE *) wreq) + sizeof(*wreq);
  436.         wreq->written = 0;
  437.         CopyMem((UBYTE *) dosPacket->dp_Arg2 + written,
  438.             wreq->buffer,
  439.             toWrite);
  440.         AddTail((struct List *) &xp->wreqList, (struct Node *) wreq);
  441. #ifdef DEBUG_HANDLER
  442.         kprintf("Handler: ACTION_WRITE, Pipe %08lx, FileHandle %08lx:\n"
  443.             "         Create write request %08lx ",
  444.             xp, xfh, wreq);
  445.         kprints(wreq->buffer, toWrite);
  446.         kprintf("         write request List:\n");
  447.         { WriteRequest *wreq;
  448.           for (wreq = (WriteRequest *) xp->wreqList.mlh_Head;
  449.            wreq->node.succ;
  450.            wreq = (WriteRequest *) wreq->node.succ)
  451.           { kprintf("        %08lx ");
  452.         kprints(wreq->buffer+wreq->written, wreq->numBytes-wreq->written);
  453.           }
  454.         }
  455. #endif
  456.       }
  457.  
  458.       ReplyPkt(dosPacket, dosPacket->dp_Arg3, 0);
  459.       break;
  460.     }
  461.     case ACTION_WAIT_CHAR:
  462.     { XBoardPipe *xp;
  463.       XBoardFileHandle *xfh;
  464.       WriteRequest *wreq;
  465.  
  466.       xfh = (XBoardFileHandle *) dosPacket->dp_Arg2;
  467.       xp = xfh->pipe;
  468.  
  469.       /**
  470.       ***  Fail, if this is not the reading filehandle.
  471.       **/
  472.       if (xfh  !=  xp->readFH)
  473.       {
  474. #ifdef DEBUG_HANDLER
  475.         kprintf("Handler: ACTION_WAIT_CHAR, Pipe %08lx, FileHandle %08lx:\n"
  476.             "         Not reading filehandle, failed.\n",
  477.             xp, xfh);
  478. #endif
  479.         ReplyPkt(dosPacket, 0, ERROR_OBJECT_WRONG_TYPE);
  480.         break;
  481.       }
  482.  
  483.       /**
  484.       ***  Fail, if the timeout argument is nonzero.
  485.       **/
  486.       if (dosPacket->dp_Arg1)
  487.       {
  488. #ifdef DEBUG_HANDLER
  489.         kprintf("Handler: ACTION_WAIT_CHAR, Pipe %08lx, FileHandle %08lx:\n"
  490.             "         Nonzero timeout argument, failed.\n",
  491.             xp, xfh);
  492. #endif
  493.         ReplyPkt(dosPacket, 0, ERROR_ACTION_NOT_KNOWN);
  494.         break;
  495.       }
  496.  
  497.       /**
  498.       ***  Check, if a WriteRequest is waiting.
  499.       **/
  500.       wreq = (WriteRequest *) xp->wreqList.mlh_Head;
  501. #ifdef DEBUG_HANDLER
  502.       kprintf("Handler: ACTION_WAIT_CHAR, Pipe %08lx, FileHandle %08lx:\n"
  503.           "         Returning %s.\n",
  504.           xp, xfh, wreq->node.succ ? "DOSTRUE" : "DOSFALSE");
  505. #endif
  506.       ReplyPkt(dosPacket, wreq->node.succ ? DOSTRUE : DOSFALSE, 0);
  507.       break;
  508.     }
  509.     case ACTION_END:
  510.     { XBoardPipe *xp;
  511.       XBoardFileHandle *xfh;
  512.  
  513.  
  514.       xfh = (XBoardFileHandle *) dosPacket->dp_Arg1;
  515.       xp = xfh->pipe;
  516.  
  517.       /**
  518.       ***  If this is the writing filehandle: Send EOF to the reading
  519.       ***  filehandle.
  520.       **/
  521.       if (xfh == xp->writeFH)
  522.       { ReadRequest *rreq;
  523.  
  524.         xp->writeFH = NULL;
  525.         while ((rreq = (ReadRequest *) xp->rreqList.mlh_Head)->node.succ)
  526.         { ReplyPkt(rreq->dp, 0, 0);
  527.           RemoveMyMinNode((MyMinNode *) rreq);
  528.         }
  529.       }
  530.       /**
  531.       ***  If it is the reading filehandle: Remove any write requests.
  532.       **/
  533.       else
  534.       { WriteRequest *wreq;
  535.  
  536.         xp->readFH = NULL;
  537.         while((wreq = (WriteRequest *) xp->wreqList.mlh_Head)->node.succ)
  538.         { RemoveMyMinNode((MyMinNode *) wreq);
  539.         }
  540.       }
  541. #ifdef DEBUG_HANDLER
  542.       kprintf("Handler: ACTION_END, Pipe %08lx, FileHandle %08lx.\n",
  543.           xp, xfh);
  544. #endif
  545.       LibFreePooled(pipesPool, xfh, sizeof(*xfh));
  546.  
  547.       if (!xp->writeFH  &&  !xp->readFH)
  548.       { RemoveMyMinNode((MyMinNode *) xp);
  549.       }
  550.  
  551.       ReplyPkt(dosPacket, DOSTRUE, 0);
  552.  
  553.       if (!diePacket)
  554.       { break;
  555.       }
  556.     }
  557.     case ACTION_DIE:
  558.       if (!diePacket)
  559.       { diePacket = dosPacket;
  560.       }
  561.       if (!xboardPipesList.mlh_Head->mln_Succ)
  562.       { ReplyPkt(diePacket, DOSTRUE, 0);
  563.         CloseLibrary((struct Library *) DOSBase);
  564. #ifdef DEBUG_HANDLER
  565.         kprintf("Handler: Terminating.\n");
  566. #endif
  567.         return;
  568.       }
  569.       break;
  570.     case ACTION_IS_FILESYSTEM:
  571. #ifdef DEBUG_HANDLER
  572.       kprintf("Handler: ACTION_IS_FILESYSTEM.\n");
  573. #endif
  574.       ReplyPkt(dosPacket, DOSFALSE, 0);
  575.       break;
  576.     case ACTION_SEEK:
  577. #ifdef DEBUG_HANDLER
  578.       kprintf("Handler: ACTION_SEEK.\n");
  579. #endif
  580.       ReplyPkt(dosPacket, -1, ERROR_ACTION_NOT_KNOWN);
  581.       break;
  582.     case ACTION_SET_FILE_SIZE:
  583. #ifdef DEBUG_HANDLER
  584.       kprintf("Handler: ACTION_SET_FILE_SIZE.\n");
  585. #endif
  586.       ReplyPkt(dosPacket, -1, ERROR_ACTION_NOT_KNOWN);
  587.       break;
  588.     default:
  589. #ifdef DEBUG_HANDLER
  590.       kprintf("Handler: Action %ld.\n", dosPacket->dp_Type);
  591. #endif
  592.       ReplyPkt(dosPacket, DOSFALSE, ERROR_ACTION_NOT_KNOWN);
  593.       break;
  594.       }
  595.     }
  596.   }
  597. }
  598. /**/
  599.  
  600.  
  601.  
  602.  
  603.  
  604. /*** pipeClose function
  605. ***
  606. ***  Close() replacement
  607. **/
  608. BOOL pipeClose(BPTR file)
  609.  
  610. { struct FileHandle *fh;
  611.  
  612.   if (file)
  613.   { fh = (struct FileHandle *) BADDR(file);
  614.     fh->fh_Type = &handlerProcess->pr_MsgPort;
  615.     return(Close(file));
  616.   }
  617.   return(TRUE);
  618. }
  619. /**/
  620.  
  621.  
  622.  
  623.  
  624.  
  625. /*** pipe function
  626. ***
  627. ***  Creates a pipe.
  628. ***
  629. ***  Inputs: fhs - a pointer to an array of BPTR's where to store
  630. ***             FileHandle's of the writing (element 0) and the
  631. ***             reading end (element 1) of the pipe. These
  632. ***             filehandles may be used for calls of Read(), Write()
  633. ***             Close() or ReadASync().
  634. ***          mode - one of MODE_NEWFILE or MODE_READWRITE, which will
  635. ***             be used to create the writing end of the pipe
  636. ***
  637. ***  Result: TRUE for sucess, FALSE otherwise; you are guaranteed,
  638. ***     that no files are open in the latter case.
  639. **/
  640. int pipe(BPTR *fhs, ULONG mode)
  641.  
  642. { struct MsgPort *oldconsoletask;
  643.   int result = FALSE;
  644.  
  645.   oldconsoletask = SetConsoleTask(&handlerProcess->pr_MsgPort);
  646.  
  647.   fhs[0] = fhs[1] = (BPTR) NULL;
  648.  
  649.   if ((fhs[0] = Open((STRPTR) "CONSOLE:", mode)))
  650.   { if ((fhs[1] = Open((STRPTR) "CONSOLE:", MODE_OLDFILE)))
  651.     { result = TRUE;
  652.     }
  653.     else
  654.     { pipeClose(fhs[0]);
  655.       fhs[0] = (BPTR) NULL;
  656.     }
  657.   }
  658.  
  659.   SetConsoleTask(oldconsoletask);
  660.   return(result);
  661. }
  662. /**/
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669. /*** Child communication section
  670. **/
  671. #define CPUser 1
  672. #define CPProc 2
  673. #define CPLoop 3
  674.  
  675. typedef int CPKind;
  676.  
  677. typedef struct {
  678.     struct MinNode node;
  679.     CPKind kind;
  680.     BPTR from[2], to[2];
  681.     BPTR msgFileHandle;
  682.     STRPTR name;
  683.     struct Process *proc;
  684. } ChildProc;
  685.  
  686. void InterruptChildProcess(ProcRef pr)
  687.  
  688. { ChildProc *cp = pr;
  689.  
  690.   if (cp->proc)
  691.   { Signal((struct Task *) cp->proc, SIGBREAKF_CTRL_C);
  692.   }
  693. }
  694.  
  695. void DestroyChildProcess(ProcRef pr)
  696.  
  697. { ChildProc *cp;
  698.  
  699.   for (cp = (ChildProc *) childProcessList.mlh_Head;
  700.        cp->node.mln_Succ;
  701.        cp = (ChildProc *) cp->node.mln_Succ)
  702.   { if ((cp == (ChildProc *) pr))
  703.     { int error;
  704.  
  705.       OutputToProcess(cp, "quit\n", 5, &error);
  706.       pipeClose(cp->to[0]);
  707.       pipeClose(cp->from[0]);
  708.       pipeClose(cp->from[1]);
  709.       pipeClose(cp->to[1]);
  710.       Remove((struct Node *) cp);
  711.       if (cp->name)
  712.       { free(cp->name);
  713.       }
  714.       free(cp);
  715.     }
  716.   }
  717. }
  718.  
  719.  
  720.  
  721.  
  722.  
  723. /**
  724. ***  This function starts a child process.
  725. ***
  726. ***  Inputs: cmdLine - the command to execute; first word will be
  727. ***             treated as binary to load, rest of line will be used
  728. ***             as arguments
  729. ***          pr - pointer where to store a process reference
  730. ***
  731. ***  Result: 0, if successful, error number otherwise
  732. **/
  733. int StartChildProcess(char *cmdLine, ProcRef *pr)
  734.  
  735. { ChildProc *cp;
  736.   int error = ENOMEM;
  737.  
  738.   fprintf(stderr, "Starting child process \"%s\".\n", cmdLine);
  739.  
  740.   if ((cp = malloc(sizeof(*cp))))
  741.   { AddTail((struct List *) &childProcessList, (struct Node *) cp);
  742.     cp->kind = CPProc;
  743.     cp->from[0] = cp->from[1] = (BPTR) NULL;
  744.     cp->to[0] = cp->to[1] = (BPTR) NULL;
  745.     cp->name = NULL;
  746.     cp->proc = NULL;
  747.  
  748.     if ((pipe(cp->from, MODE_READWRITE)))
  749.     { if ((pipe(cp->to, MODE_NEWFILE)))
  750.       { cp->msgFileHandle = ((struct FileHandle *) BADDR(cp->from[0]))->fh_Arg1;
  751.  
  752.     if ((cp->name = (STRPTR) strdup(cmdLine)))
  753.     { BPTR lock;
  754.       STRPTR args, name;
  755.  
  756.       /*
  757.           Let name point to the command name and args to the
  758.           arguments.
  759.       */
  760.       name = cp->name;
  761.       while (isspace(*name))
  762.       { name++;
  763.       }
  764.  
  765.       if (*name == '"')
  766.       { name++;
  767.         if ((args = (STRPTR) strchr((char *) name, '"')))
  768.         { *args++ = '\0';
  769.         }
  770.         else
  771.         { args = (STRPTR) "";
  772.         }
  773.       }
  774.       else
  775.       { args = name;
  776.         while (*args  &&  !isspace(*args))
  777.         { ++args;
  778.         }
  779.         if (*args)
  780.         { *args++ = '\0';
  781.         }
  782.       }
  783.  
  784.       if ((lock = Lock(name, SHARED_LOCK)))
  785.       { BPTR parentLock;
  786.  
  787.         parentLock = ParentDir(lock);
  788.         UnLock(lock);
  789.  
  790.         if (parentLock)
  791.         { BPTR segList;
  792.  
  793.           if ((segList = NewLoadSeg(name, NULL)))
  794.           { cp->proc = CreateNewProcTags(
  795.                 NP_Seglist, segList,
  796.                 NP_Input, cp->to[1],
  797.                 NP_Output, cp->from[0],
  798.                 NP_StackSize, amigaAppData.childStack,
  799.                 NP_Name, FilePart(cp->name),
  800.                 NP_Priority, amigaAppData.childPriority,
  801.                 NP_HomeDir, parentLock,
  802.                 NP_CopyVars, FALSE,
  803.                 NP_Cli, TRUE,
  804.                 NP_CommandName, name,
  805.                 NP_Arguments, args,
  806.                 TAG_DONE);
  807.         if (cp->proc)
  808.         {
  809. #ifdef DEBUG_HANDLER
  810.           kprintf("Childprocess `%s' created.\n", cmdLine);
  811. #endif
  812.           cp->from[0] = (BPTR) NULL;
  813.           cp->to[1] = (BPTR) NULL;
  814.           *pr = cp;
  815.           return(0);
  816.         }
  817.         UnLoadSeg(segList);
  818.           }
  819.           UnLock(parentLock);
  820.         }
  821.       }
  822.       else
  823.       { error = ENOENT;
  824.       }
  825.     }
  826.       }
  827.     }
  828.   }
  829.  
  830.   DestroyChildProcess(cp);
  831.   *pr = NULL;
  832.   return(error);
  833. }
  834.  
  835. int OpenLoopback(ProcRef *pr)
  836.  
  837. { ChildProc *cp;
  838.   int error = 0;
  839.  
  840.   if ((cp = malloc(sizeof(*cp))))
  841.   { cp->kind = CPLoop;
  842.     cp->from[0] = cp->from[1] = (BPTR) NULL;
  843.     cp->to[0] = cp->to[1] = (BPTR) NULL;
  844.  
  845.     if (pipe(cp->to, MODE_READWRITE))
  846.     { cp->msgFileHandle = cp->to[0];
  847.       cp->from[1] = cp->to[1];
  848.       cp->to[1] = (BPTR) NULL;
  849.     }
  850.     else
  851.     { error = ENOMEM;
  852.     }
  853.   }
  854.   else
  855.   { error = ENOMEM;
  856.   }
  857.  
  858.   return(error);
  859. }
  860. /**/
  861.  
  862.  
  863.  
  864.  
  865.  
  866. /**
  867. ***  Child process functions
  868. **/
  869. int OpenTelnet(char *host, int port, ProcRef *pr)
  870.  
  871. { char cmdLine[MSG_SIZ];
  872.  
  873.   sprintf(cmdLine, "%s %s %d", appData.telnetProgram, host, port);
  874.   return(StartChildProcess(cmdLine, pr));
  875. }
  876.  
  877. int OpenTCP(char *host, int port, ProcRef *pr)
  878.  
  879. { DisplayFatalError("Socket support is not configured in.", 0, 2);
  880.   return(ENOENT);
  881. }
  882.  
  883. int OpenCommPort(char *name, ProcRef *pr)
  884.  
  885. { DisplayFatalError("Serial line support is not configured in.", 0, 2);
  886.   return(ENOENT);
  887. }
  888.  
  889. int OpenRcmd(char *host, char *user, char *cmd, ProcRef *pr)
  890.  
  891. { DisplayFatalError("Internal rcmd not implemented.", 0, 10);
  892.   return(-1);
  893. }
  894.  
  895.  
  896.  
  897. /*** Input source section
  898. */
  899. #define INPUT_SOURCE_BUF_SIZE 4096
  900.  
  901. typedef struct
  902. { struct MinNode node;
  903.   CPKind kind;
  904.   int lineByLine;
  905.   InputCallback func;
  906.   ChildProc *cp;
  907.   struct MsgPort *mp;
  908.   LONG cis_Arg1;
  909.   FILE *fp;
  910.   struct MsgPort *cisPort;
  911.   struct DosPacket *dp;
  912.   BOOL dpsent;
  913.   char buf[INPUT_SOURCE_BUF_SIZE];
  914. } InputSource;
  915.  
  916. void DoInputCallback(ULONG receivedsigs)
  917.  
  918. { struct Message *msg;
  919.   struct DosPacket *dp;
  920.   InputSource *is;
  921.  
  922.   if (receivedsigs & (1 << pipesPort->mp_SigBit))
  923.   { while((msg = GetMsg(pipesPort)))
  924.     { dp = (struct DosPacket *) msg->mn_Node.ln_Name;
  925.  
  926.       switch (dp->dp_Type)
  927.       { case ACTION_END:
  928.     case ACTION_WRITE:
  929.       for (is = (InputSource *) inputSourceList.mlh_Head;
  930.            dp  &&  is->node.mln_Succ;
  931.            is = (InputSource *) is->node.mln_Succ)
  932.       { if (is->kind == CPProc  &&  is->cp->msgFileHandle == dp->dp_Arg1)
  933.         { if (dp->dp_Type == ACTION_END)
  934.           {
  935. #ifdef DEBUG_HANDLER
  936.         kprintf("DoInputCallback: ACTION_END, Arg1 = %ld.\n"
  937.             "                 Telling frontend and sending to handler.\n",
  938.             dp->dp_Arg1, dp->dp_Arg2, dp->dp_Arg3);
  939. #endif
  940.         PutMsg(&handlerProcess->pr_MsgPort, msg);
  941.         (is->func)((InputSourceRef) is, is->buf, 0, 0);
  942.           }
  943.           else
  944.           { int len = dp->dp_Arg3;
  945.  
  946.         memcpy(is->buf, (char *) dp->dp_Arg2, len);
  947.         is->buf[len] = NULLCHAR;
  948. #ifdef DEBUG_HANDLER
  949.         kprintf("DoInputCallback: ACTION_WRITE, Arg1 = %ld, Arg2 = %ld, Arg3 = %ld.\n"
  950.             "                 Replying okay. ",
  951.             dp->dp_Type, dp->dp_Arg1, dp->dp_Arg2, dp->dp_Arg3);
  952.         kprints((char *) dp->dp_Arg2, dp->dp_Arg3);
  953. #endif
  954.         ReplyPkt(dp, len, 0);
  955.         (is->func)((InputSourceRef) is, is->buf, len, 0);
  956.           }
  957.           dp = NULL;
  958.           break;
  959.         }
  960.       }
  961.       if (dp)
  962.       {
  963. #ifdef DEBUG_HANDLER
  964.         if (dp->dp_Type == ACTION_END)
  965.         { kprintf("DoInputCallback: ACTION_END, Arg1 = %ld.\n"
  966.               "                 Sending to handler.\n",
  967.               dp->dp_Arg1, dp->dp_Arg2, dp->dp_Arg3);
  968.         }
  969.         else
  970.         { kprintf("DoInputCallback: Type = %ld, Arg1 = %ld, Arg2 = %ld, Arg3 = %ld.\n"
  971.               "                 Pipe unknown, replying okay. ",
  972.               dp->dp_Type, dp->dp_Arg1, dp->dp_Arg2, dp->dp_Arg3);
  973.           kprints((char *) dp->dp_Arg2, dp->dp_Arg3);
  974.         }
  975. #endif
  976.         PutMsg(&handlerProcess->pr_MsgPort, msg);
  977.       }
  978.       break;
  979.  
  980.     default:
  981.       /**
  982.       ***  This is for the handler, redirect it.
  983.       **/
  984. #ifdef DEBUG_HANDLER
  985.       kprintf("DoInputCallback: Type = %ld, Arg1 = %ld, Arg2 = %ld, Arg3 = %ld.\n"
  986.           "                 Redirecting to handler.\n",
  987.           dp->dp_Type, dp->dp_Arg1, dp->dp_Arg2, dp->dp_Arg3);
  988. #endif
  989.       PutMsg(&handlerProcess->pr_MsgPort, msg);
  990.       break;
  991.       }
  992.  
  993.     }
  994.   }
  995.  
  996.   for (is = (InputSource *) inputSourceList.mlh_Head;
  997.        is->node.mln_Succ;
  998.        is = (InputSource *) is->node.mln_Succ)
  999.   { if (is->kind == CPUser  &&  (receivedsigs & (1 << is->mp->mp_SigBit)))
  1000.     { msg = GetMsg(is->mp);
  1001.       dp = (struct DosPacket *) msg->mn_Node.ln_Name;
  1002.       if (dp == is->dp)
  1003.       { is->dpsent = FALSE;
  1004.     if (dp->dp_Res1 > 0)
  1005.     { is->buf[dp->dp_Res1] = '\0';
  1006.     }
  1007. #ifdef DEBUG_HANDLER
  1008.     kprintf("DoInputCallback: ICS Input ");
  1009.     kprints((char *) dp->dp_Arg2, dp->dp_Res1);
  1010. #endif
  1011.     (is->func)((InputSourceRef) is, is->buf, dp->dp_Res1, 0);
  1012.     dp->dp_Type = ACTION_READ;
  1013.     dp->dp_Arg1 = is->cis_Arg1;
  1014.     dp->dp_Arg2 = (ULONG) is->buf;
  1015.     dp->dp_Arg3 = sizeof(is->buf)-1;
  1016.     SendPkt(dp, is->cisPort, is->mp);
  1017.     is->dpsent = TRUE;
  1018.       }
  1019.     }
  1020.   }
  1021. }
  1022.  
  1023.  
  1024. InputSourceRef AddInputSource(ProcRef pr, int lineByLine, InputCallback func)
  1025.  
  1026. { InputSource *is;
  1027.   ChildProc *cp = (ChildProc *) pr;
  1028.   ULONG success = FALSE;;
  1029.  
  1030.   if ((is = (InputSource *) malloc(sizeof(*is))))
  1031.   { AddTail((struct List *) &inputSourceList, (struct Node *) is);
  1032.     is->lineByLine = lineByLine;
  1033.     is->func = func;
  1034.     is->cp = cp;
  1035.     is->fp = NULL;
  1036.     is->dp = NULL;
  1037.     is->mp = NULL;
  1038.     if (pr != NoProc)
  1039.     { is->kind = cp->kind;
  1040.       success = TRUE;
  1041.     }
  1042.     else
  1043.     { ULONG windowOpen = FALSE;
  1044.  
  1045.       /**
  1046.       ***  Open a window, if required.
  1047.       **/
  1048.       if (amigaAppData.icsWindow  ||  !Input()  ||  !Output())
  1049.       { char *winName;
  1050.     BPTR cos;
  1051.  
  1052.     if (!(winName = (char *) amigaAppData.icsWindow))
  1053.     { winName = "CON:////ICS";
  1054.     }
  1055.  
  1056.     if ((is->fp = toUserFP = fopen(winName, "r+")))
  1057.     { if ((cos = (BPTR) fdtofh(fileno(toUserFP))))
  1058.       { is->cis_Arg1 = ((struct FileHandle *) BADDR(cos))->fh_Arg1;
  1059.         is->cisPort = ((struct FileHandle *) BADDR(cos))->fh_Type;
  1060.         windowOpen = TRUE;
  1061.       }
  1062.     }
  1063.     if (!windowOpen)
  1064.     { DisplayFatalError("Can't open window %s.\nOut of memory?", 0, 10);
  1065.     }
  1066.       }
  1067.       else
  1068.       { is->cis_Arg1 = ((struct FileHandle *) BADDR(Input()))->fh_Arg1;
  1069.     is->cisPort = ((struct FileHandle *) BADDR(Input()))->fh_Type;
  1070.     windowOpen = TRUE;
  1071.       }
  1072.  
  1073.       if (windowOpen)
  1074.       { is->kind = CPUser;
  1075.     is->dpsent = FALSE;
  1076.     if ((is->dp = AllocDosObject(DOS_STDPKT, NULL)))
  1077.     { if ((is->mp = CreateMsgPort()))
  1078.       { is->dp->dp_Type = ACTION_READ;
  1079.         is->dp->dp_Arg1 = is->cis_Arg1;
  1080.         is->dp->dp_Arg2 = (ULONG) is->buf;
  1081.         is->dp->dp_Arg3 = sizeof(is->buf) - 1;
  1082.         SendPkt(is->dp, is->cisPort, is->mp);
  1083.         is->dpsent = TRUE;
  1084.         success = TRUE;
  1085.         pipeSignals |= (1 << is->mp->mp_SigBit);
  1086.       }
  1087.     }
  1088.       }
  1089.     }
  1090.   }
  1091.  
  1092.   if (!success)
  1093.   { RemoveInputSource(is);
  1094.     is = NULL;
  1095.   }
  1096.  
  1097.   return(is);
  1098. }
  1099.  
  1100. void RemoveInputSource(InputSourceRef isr)
  1101.  
  1102. { InputSource *is;
  1103.  
  1104.   for (is = (InputSource *) inputSourceList.mlh_Head;
  1105.        is->node.mln_Succ;
  1106.        is = (InputSource *) is->node.mln_Succ)
  1107.   { if (is == isr)
  1108.     { if (is->kind == CPUser)
  1109.       { if (is->dpsent)
  1110.     { DoPkt3(is->cisPort, ACTION_STACK, is->cis_Arg1, (ULONG) "\n", 1);
  1111.       AbortPkt(is->cisPort, is->dp);
  1112.       WaitPort(is->mp);
  1113.       GetMsg(is->mp);
  1114.     }
  1115.     if (is->mp)
  1116.     { pipeSignals &= ~(1 << is->mp->mp_SigBit);
  1117.       DeleteMsgPort(is->mp);
  1118.     }
  1119.     if (is->dp)
  1120.     { FreeDosObject(DOS_STDPKT, is->dp);
  1121.     }
  1122.     if (is->fp)
  1123.     { fclose(is->fp);
  1124.     }
  1125.       }
  1126.       else if (is->kind == CPProc)
  1127.       { DestroyChildProcess(is->cp);
  1128.       }
  1129.  
  1130.       Remove((struct Node *) is);
  1131.       free(is);
  1132.       break;
  1133.     }
  1134.   }
  1135. }
  1136.  
  1137. int OutputToProcess(ProcRef pr, char *message, int count, int *outError)
  1138.  
  1139. { ChildProc *cp;
  1140.   int outCount;
  1141.  
  1142.   for (cp = (ChildProc *) childProcessList.mlh_Head;
  1143.        cp->node.mln_Succ;
  1144.        cp = (ChildProc *) cp->node.mln_Succ)
  1145.   { if (cp == (ChildProc *) pr)
  1146.     { if ((outCount = Write(cp->to[0], message, count))  ==  count)
  1147.       { *outError = 0;
  1148.       }
  1149.       else
  1150.       { *outError = ENOMEM;
  1151.       }
  1152.       return(outCount);
  1153.     }
  1154.   }
  1155.   *outError = ENOENT;
  1156.   return(0);
  1157. }
  1158. /**/
  1159.  
  1160.  
  1161.  
  1162.  
  1163. /*** popen function
  1164. ***
  1165. ***  *Very* simple replacement
  1166. **/
  1167. FILE *popen(const char *cmdLine, const char *mode)
  1168.  
  1169. { char buf[L_tmpnam+5];
  1170.   FILE *fp = NULL;
  1171.   BPTR fileHandle;
  1172.   int error = ENOENT;
  1173.  
  1174.   strcpy(buf, "PIPE:");
  1175.   tmpnam(buf+5);
  1176.  
  1177.   if ((fileHandle = Open((STRPTR) buf, MODE_NEWFILE)))
  1178.   { if ((fp = fopen(buf, "r")))
  1179.     { if (!SystemTags((STRPTR) cmdLine, SYS_Output, fileHandle))
  1180.       { error = 0;
  1181.       }
  1182.       else
  1183.       { fclose(fp);
  1184.     fp = NULL;
  1185.       }
  1186.     }
  1187.     Close(fileHandle);
  1188.   }
  1189.  
  1190.   errno = error;
  1191.   return(fp);
  1192. }
  1193.  
  1194. int pclose(FILE *fp)
  1195.  
  1196. { if (fp)
  1197.   { return(fclose(fp));
  1198.   }
  1199.   return(0);
  1200. }
  1201. /**/
  1202.  
  1203.  
  1204.  
  1205.  
  1206.  
  1207. /*** PipesClose function
  1208. ***
  1209. ***  Terminates the handler process by sending him
  1210. ***  an ACTION_DIE packet and waiting for the reply.
  1211. ***  (This guarantees, that the child process
  1212. ***  terminates first.
  1213. **/
  1214. VOID PipesClose(VOID)
  1215.  
  1216. { ChildProc *cp;
  1217.   InputSource *is;
  1218.  
  1219.   while ((is = (InputSource *) inputSourceList.mlh_Head)->node.mln_Succ)
  1220.   { RemoveInputSource((InputSourceRef) is);
  1221.   }
  1222.  
  1223.   while ((cp = (ChildProc *) childProcessList.mlh_Head)->node.mln_Succ)
  1224.   { DestroyChildProcess((ProcRef) cp);
  1225.   }
  1226.  
  1227.   if (handlerProcess)
  1228.   { pipesPacket->dp_Type = ACTION_DIE;
  1229.     SendPkt(pipesPacket, &handlerProcess->pr_MsgPort, pipesPort);
  1230.   }
  1231.  
  1232.   if (pipesPort)
  1233.   { ULONG childProcessRunning = TRUE;
  1234.  
  1235.     while (childProcessRunning)
  1236.     { struct Message *message;
  1237.  
  1238.       WaitPort(pipesPort);
  1239.       while ((message = GetMsg(pipesPort)))
  1240.       { struct DosPacket *dosPacket = (struct DosPacket *) message->mn_Node.ln_Name;
  1241.  
  1242.     switch (dosPacket->dp_Type)
  1243.     { case ACTION_DIE:
  1244.         childProcessRunning = FALSE;
  1245.         break;
  1246.       case ACTION_WRITE:
  1247. #ifdef DEBUG_HANDLER
  1248.         kprintf("PipesClose: Type = %ld, Arg1 = %ld, Arg2 = %ld, Arg3 = %ld.\n"
  1249.             "            Replying okay. ",
  1250.             dosPacket->dp_Type, dosPacket->dp_Arg1, dosPacket->dp_Arg2, dosPacket->dp_Arg3);
  1251.         kprints((char *) dosPacket->dp_Arg2, dosPacket->dp_Arg3);
  1252. #endif
  1253.         ReplyPkt(dosPacket, dosPacket->dp_Arg3, 0);
  1254.         break;
  1255.       default:
  1256. #ifdef DEBUG_HANDLER
  1257.         kprintf("PipesClose: Type = %ld, Arg1 = %ld, Arg2 = %ld, Arg3 = %ld.\n"
  1258.             "            Redirecting to handler.\n",
  1259.             dosPacket->dp_Type, dosPacket->dp_Arg1, dosPacket->dp_Arg2, dosPacket->dp_Arg3);
  1260. #endif
  1261.         PutMsg(&handlerProcess->pr_MsgPort, message);
  1262.         break;
  1263.     }
  1264.       }
  1265.     }
  1266.     DeleteMsgPort(pipesPort);
  1267.   }
  1268.  
  1269.   if (pipesPool)
  1270.   { LibDeletePool(pipesPool);
  1271.   }
  1272.  
  1273.   if (pipesPacket)
  1274.   { FreeDosObject(DOS_STDPKT, pipesPacket);
  1275.   }
  1276. }
  1277. /**/
  1278.  
  1279.  
  1280.  
  1281.  
  1282.  
  1283. /*** PpipesInit function
  1284. ***
  1285. ***  Initialize the handler.
  1286. **/
  1287. VOID PipesInit(VOID)
  1288.  
  1289. { NewList((struct List *) &inputSourceList);
  1290.   NewList((struct List *) &childProcessList);
  1291.  
  1292.   /**
  1293.   ***  Allocate a dos packet
  1294.   **/
  1295.   if ((pipesPacket = AllocDosObject(DOS_STDPKT, NULL)))
  1296.   { if ((pipesPort = CreateMsgPort()))
  1297.     { pipeSignals = (1 << pipesPort->mp_SigBit);
  1298.       if ((pipesPool = LibCreatePool(MEMF_ANY, 4096, 2048)))
  1299.       { if ((handlerProcess = CreateNewProcTags(NP_Entry, xboardPipesHandler,
  1300.                         NP_Name, "AmyBoard pipe handler",
  1301.                         NP_CopyVars, FALSE,
  1302.                         TAG_DONE)))
  1303.     { return;
  1304.     }
  1305.       }
  1306.  
  1307.       DeleteMsgPort(pipesPort);
  1308.       pipesPort = NULL;
  1309.     }
  1310.   }
  1311.   exit(10);
  1312. }
  1313. /**/
  1314.