home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / reference / amiga_mail_vol2 / ii-95 / inoutctrl-c.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  11KB  |  221 lines

  1. ;/* InOutCTRL-C.c - Execute me to compile me with SAS/C 6.56
  2. sc DATA=FAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 InOutCTRL-C.c
  3. slink FROM LIB:c.o,InOutCTRL-C.o TO InOutCTRL-C LIBRARY LIB:sc.lib,LIB:amiga.lib,lib:debug.lib
  4. quit ;*/
  5.  
  6. /* (c)  Copyright 1992 Commodore-Amiga, Inc.   All rights reserved.       */
  7. /* The information contained herein is subject to change without notice,  */
  8. /* and is provided "as is" without warranty of any kind, either expressed */
  9. /* or implied.  The entire risk as to the use of this information is      */
  10. /* assumed by the user.                                                   */
  11.  
  12.  
  13. /* InOutCTRL-C.c uses packets to copy the standard input channel to the        */
  14. /* standard output channel using asynchronous I/O.  This example does a better */
  15. /* job checking for a user break than the accompanying example, CompareIO.c.   */
  16.  
  17. #include <exec/types.h>
  18. #include <dos/dosextens.h>
  19.  
  20. #include <clib/dos_protos.h>
  21. #include <clib/exec_protos.h>
  22. #include <clib/alib_protos.h>
  23. #include <clib/alib_stdio_protos.h>
  24.  
  25. #ifdef LATTICE
  26. int CXBRK(void) { return(0); }                    /* Disable Lattice CTRL/C handling */
  27. void chkabort(void) { return; }
  28. #endif
  29.  
  30.  
  31. #define BUFSIZE 8192
  32.  
  33. UBYTE *vers = "\0$VER: InOutCTRL-C 37.9 Nov-12-92";
  34.  
  35. void MainLoop(void);
  36.  
  37. extern struct Library *DOSBase;
  38.  
  39. struct MsgPort  *myport;
  40. ULONG portsignal, signals, sigmask;
  41.  
  42. struct FileHandle *in, *out;
  43. struct DosPacket *sp_read, *sp_write;
  44.  
  45. UBYTE buf1[BUFSIZE], buf2[BUFSIZE];
  46.  
  47. void main(void)
  48. {
  49.   if (DOSBase->lib_Version >= 37)                                        /* 2.0 only */
  50.   {
  51.     if (myport = CreateMsgPort())
  52.     {
  53.       if (in = (struct FileHandle *)BADDR(Input()))        /* Need file handle to    */
  54.       {                                                    /* get to Handler process */
  55.         if (out = (struct FileHandle *)BADDR(Output()))
  56.         {
  57.           if (sp_read = AllocDosObject(DOS_STDPKT, NULL))    /* Allocate two         */
  58.           {                                                  /* StandardPackets: one */
  59.             if (sp_write = AllocDosObject(DOS_STDPKT, NULL)) /* for reading, and one */
  60.             {                                                /* for writing. */
  61.  
  62.               sp_read->dp_Type = ACTION_READ;    /* Fill out the ACTION_READ packet. */
  63.               sp_read->dp_Arg1 = in->fh_Arg1;
  64.               sp_read->dp_Arg2 = (LONG)buf1;     /* The buffer to fill in.           */
  65.               sp_read->dp_Arg3 = BUFSIZE;        /* The size of the Arg2 buffer.     */
  66.  
  67.                        /* When AllocDosObject() allocates a StandardPacket, it takes */
  68.                        /* care of linking together the Message and DosPacket.        */
  69.                        /* AllocDosObject() points the DosPacket's dp_Link field at   */
  70.                        /* the StandardPacket's Message structure.  It also points    */
  71.                        /* the Message's mn_Node.ln_Name field at the DosPacket:      */
  72.                        /*                 sp_read->dp_Link = sp_Msg;                 */
  73.                        /*                 sp_Msg->mn_Node.ln_Name = (STRPTR)sp_read; */
  74.  
  75.  
  76.               if (!((out->fh_Arg1) && (in->fh_Arg1)))     /* Don't bother if in or   */
  77.                 return;                                   /*          out uses NIL:  */
  78.  
  79.               SendPkt(sp_read, in->fh_Type, myport);   /* Send initial read request. */
  80.  
  81.               portsignal = 1L<<myport->mp_SigBit;          /* Record the signal bits */
  82.               sigmask    = SIGBREAKF_CTRL_C | portsignal;  /*         for later use. */
  83.  
  84.               sp_write->dp_Type = ACTION_WRITE; /* Fill out the ACTION_WRITE packet. */
  85.               sp_write->dp_Arg1 = out->fh_Arg1;
  86.               sp_write->dp_Arg2 = (LONG)buf2;  /* Arg2 points to the buffer to write */
  87.               sp_write->dp_Arg3 = 0L;          /* out.  At first glance, it might    */
  88.               sp_write->dp_Res1 = 0L;          /* seem odd to bother setting Arg2    */
  89.                                       /* when the program hasn't read anything yet.  */
  90.                                       /* This is to set up for the main loop.  The   */
  91.                                       /* main loop swaps the ACTION_READ buffer with */
  92.                                       /* the ACTION_WRITE buffer when it receives    */
  93.                                       /* a completed read.  Likewise, dp_Arg3 and    */
  94.                                       /* dp_Res1 are set to make the ACTION_READ     */
  95.                                       /* look like it has a valid return value so    */
  96.                                       /* main loop won't fail the first time through */
  97.                                       /* the loop.                                   */
  98.               MainLoop();
  99.               FreeDosObject(DOS_STDPKT, sp_write);
  100.             }
  101.             FreeDosObject(DOS_STDPKT, sp_read);
  102.           }
  103.         }
  104.       }
  105.       DeleteMsgPort(myport);
  106.     }
  107.   }
  108. }
  109.  
  110.  
  111. void MainLoop()
  112. {
  113. struct StandardPacket *mysp;
  114. UBYTE *buf;
  115.  
  116. LONG amount_read;
  117.  
  118. BOOL sp_read_busy  = TRUE,                    /*    Is the ACTION_READ packet busy?  */
  119.      sp_write_busy = FALSE,                   /*    Is the ACTION_WRITE packet busy? */
  120.      done           = FALSE;                  /*    Is the program finished?         */
  121.  
  122.                 /* main() has already taken care of sending the initial read to the  */
  123.                 /* handler.  Because we need the data from that read before we can   */
  124.   while (!done) /* do anything, the first thing to do is wait for its return.        */
  125.   {
  126.     do                                   /*      Wait for the ACTION_READ to return. */
  127.     {
  128.       signals = Wait(sigmask);           /*          Wait for port signal or CTRL-C. */
  129.  
  130.       if (signals & portsignal)          /* If a message arrived at the port, ...    */
  131.       {
  132.         while (mysp = (struct StandardPacket *)GetMsg(myport)) /* ...empty the port. */
  133.         {
  134.                           /* If this message is the ACTION_READ packet, mark it as   */
  135.                           /* no longer busy so we can use it to start another read.  */
  136.           if (mysp->sp_Pkt.dp_Type == ACTION_READ)    sp_read_busy  = FALSE;
  137.  
  138.                           /* If this message is instead the ACTION_WRITE packet,     */
  139.                           /* mark it as not busy.  We need to check for this because */
  140.                           /* the WRITE_PACKET from the previous interation through   */
  141.                           /* the loop might have come back before the ACTION_WRITE   */
  142.                           /* from the previous interation.                           */
  143.           else
  144.             if (mysp->sp_Pkt.dp_Type == ACTION_WRITE) sp_write_busy = FALSE;
  145.         }
  146.       }
  147.  
  148.       if (signals & SIGBREAKF_CTRL_C) /* If someone hit CTRL-C, start to quit. */
  149.       {
  150.         done = TRUE;                      /* If the ACTION_READ is still out, try to */
  151.         if (sp_read_busy)                 /* abort it.  As of V39, AbortPkt() does   */
  152.           AbortPkt(in->fh_Type, sp_read); /* not do anything, so this function has   */
  153.       }                                   /* no effect. Maybe a later release of the */
  154.                                           /* OS will support packet aborting.        */
  155.  
  156.  
  157.     } while (sp_read_busy);                   /* End of "wait for ACTION_READ" loop. */
  158.  
  159.                                           /* Get ready to send the next ACTION_READ. */
  160.     buf = (UBYTE *)(sp_read->dp_Arg2);    /* Hold on to the important stuff from the */
  161.     amount_read = sp_read->dp_Res1;       /* ACTION_READ we just got back so we can  */
  162.                                           /* reuse the packet to start a new read    */
  163.                                           /* while processing the last read's data.  */
  164.  
  165.     while (sp_write_busy)          /* Because this example only uses two buffers and */
  166.     {                              /* the ACTION_WRITE might be using one of them,   */
  167.                                    /* this example has to wait for an outstanding    */
  168.                                    /* ACTION_WRITE to return before reusing the      */
  169.                                    /* ACTION_WRITE packet's buffer.                  */
  170.       signals = Wait(sigmask);
  171.  
  172.       if (signals & portsignal)           /*  If a message arrived at the port, ...  */
  173.       {                                              /*          ... empty the port. */
  174.         while (mysp = (struct StandardPacket *)GetMsg(myport))
  175.           if (mysp->sp_Pkt.dp_Type == ACTION_WRITE) sp_write_busy = FALSE;
  176.       }
  177.  
  178.       if (signals & SIGBREAKF_CTRL_C)     /*   If someone hit CTRL-C, start to quit. */
  179.       {
  180.         done = TRUE;                      /* If the ACTION_READ is still out, try to */
  181.         if (sp_write_busy) AbortPkt(out->fh_Type, sp_write);            /* abort it. */
  182.       }
  183.     }
  184.  
  185.                /* Make sure the user didn't hit CTRL-C.  If the user hit CTRL-C dur- */
  186.     if (!done) /* ing one of the "wait for packet" loops, done == TRUE.  Notice that */
  187.     {          /* this example does not actually break for the CTRL-C until after it */
  188.                /* gets back both packets.                                            */
  189.  
  190.                /* This tests the return values from the ACTION_READ and ACTION_WRITE */
  191.                /* packets.  The ACTION_READ packet returns the number of bytes it    */
  192.                /* read in dp_Res1, which was copied earlier into amount_read. If it  */
  193.                /* is 0, the read packet found the EOF.  If it is negative, there was */
  194.                /* an error.  In the case of ACTION_WRITE, an error occurs if the     */
  195.                /* number of bytes that ACTION_WRITE was supposed to write (Arg3)     */
  196.                /* does not match the actual number it wrote, which ACTION_WRITE re-  */
  197.                /* turns in Res1.  This test is the reason dp_Res1 and dp_Arg3 were   */
  198.                /* set to zero when the ACTION_WRITE packet was set up in main().     */
  199.       if ((amount_read > 0) && (sp_write->dp_Res1 == sp_write->dp_Arg3))
  200.       {
  201.         sp_read->dp_Arg2 = sp_write->dp_Arg2;  /* ACTION_WRITE is finished with its  */
  202.                                                /* buffer, use it in the next read.   */
  203.  
  204.         SendPkt(sp_read, in->fh_Type, myport); /* Send the next ACTION_READ and mark */
  205.         sp_read_busy = TRUE;                   /* the ACTION_READ as busy.           */
  206.  
  207.         /* Process Buffer.  This example doesn't do anything with the data from the  */
  208.         /* last ACTION_READ, it just passes it on to the STDOUT handler.             */
  209.  
  210.  
  211.         sp_write->dp_Arg2 = (LONG)buf;         /*    Set up the ACTION_WRITE packet. */
  212.         sp_write->dp_Arg3 = amount_read;
  213.         SendPkt(sp_write, out->fh_Type, myport);   /* Send the next ACTION_WRITE and */
  214.         sp_write_busy = TRUE;                      /* mark the ACTION_WRITE as busy. */
  215.       }
  216.       else                             /* A packet returned with a failure, so quit. */
  217.         done = TRUE;
  218.     }
  219.   }
  220. }
  221.