home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1996 October / PCO_10.ISO / filesbbs / bsrc_260.arj / SRC.ZIP / zsend.c < prev   
Encoding:
C/C++ Source or Header  |  1996-02-20  |  29.2 KB  |  1,104 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software, Co.                       */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          Freely Available<tm> Software.                 */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*              (C) Copyright 1987-96, Bit Bucket Software Co.              */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /*                    Zmodem file transmission module                       */
  15. /*                                                                          */
  16. /*                                                                          */
  17. /*    For complete  details  of the licensing restrictions, please refer    */
  18. /*    to the License  agreement,  which  is published in its entirety in    */
  19. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    */
  20. /*                                                                          */
  21. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  22. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  23. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  24. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  25. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  26. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  27. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  28. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  29. /*                                                                          */
  30. /*                                                                          */
  31. /* You can contact Bit Bucket Software Co. at any one of the following      */
  32. /* addresses:                                                               */
  33. /*                                                                          */
  34. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
  35. /* P.O. Box 460398                AlterNet 7:42/1491                        */
  36. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  37. /*                                Internet f491.n343.z1.fidonet.org         */
  38. /*                                                                          */
  39. /* Please feel free to contact us at any time to share your comments about  */
  40. /* our software and/or licensing policies.                                  */
  41. /*                                                                          */
  42. /*                                                                          */
  43. /*  This module is based largely on a similar module in OPUS-CBCS V1.03b.   */
  44. /*  The original work is (C) Copyright 1986, Wynn Wagner III. The original  */
  45. /*  authors have graciously allowed us to use their code in this work.      */
  46. /*                                                                          */
  47. /*--------------------------------------------------------------------------*/
  48.  
  49. /* Include this file before any other includes or defines! */
  50.  
  51. #include "includes.h"
  52.  
  53. /*--------------------------------------------------------------------------*/
  54. /* Private routines                                                         */
  55. /*--------------------------------------------------------------------------*/
  56.  
  57. static void LOCALFUNC ZS_SendBinaryHeader (unsigned short, byte *);
  58. static void LOCALFUNC ZS_32SendBinaryHeader (unsigned short, byte *);
  59. static void LOCALFUNC ZS_SendData (byte *, int, unsigned short);
  60. static void LOCALFUNC ZS_32SendData (byte *, int, unsigned short);
  61. static void LOCALFUNC ZS_SendByte (byte);
  62. static int LOCALFUNC ZS_GetReceiverInfo (void);
  63. static int LOCALFUNC ZS_SendFile (int, int);
  64. static int LOCALFUNC ZS_SendFileData (int);
  65. static int LOCALFUNC ZS_SyncWithReceiver (int);
  66. static void LOCALFUNC ZS_EndSend (void);
  67.  
  68. /*--------------------------------------------------------------------------*/
  69. /* Private data                                                             */
  70. /*--------------------------------------------------------------------------*/
  71.  
  72. static FILE *Infile;            /* Handle of file being sent */
  73. static long Strtpos;            /* Starting byte position of */
  74.                                 /* download                  */
  75.  
  76. static long LastZRpos;            /* Last error location       */
  77. static long ZRPosCount;            /* ZRPOS repeat count        */
  78. static long Txpos;                /* Transmitted file position */
  79. static int Rxbuflen;            /* Receiver's max buffer     */
  80.                                 /* length                    */
  81.  
  82. static int Rxflags;                /* Receiver's flags          */
  83.  
  84. /*--------------------------------------------------------------------------*/
  85. /* SEND ZMODEM (send a file)                                                */
  86. /*   returns TRUE (1) for good xfer, FALSE (0) for bad                      */
  87. /*   sends one file per call; 'fsent' flags start and end of batch          */
  88. /*--------------------------------------------------------------------------*/
  89.  
  90. int 
  91. Send_Zmodem (char *fname, char *alias, int fsent, int wazoo)
  92. {
  93.     register byte *p;
  94.     register byte *q;
  95.     struct stat f;
  96.     long ltemp;
  97.     int rc = TRUE;
  98.     char j[100];
  99.     time_t filetime;
  100.  
  101. #ifdef DEBUG
  102.     show_debug_name ("send_Zmodem");
  103. #endif
  104.  
  105.     IN_XON_ENABLE ();
  106.  
  107.     z_size = 0;
  108.     Infile = NULL;
  109.  
  110.     if (fname && !(fullscreen && un_attended))
  111.         set_xy ("");
  112.  
  113.     switch (fsent)
  114.     {
  115.     case 0:
  116.  
  117.         Z_PutString ((byte *) "rz\r");
  118.         Z_PutLongIntoHeader (0L);
  119.         Z_SendHexHeader (ZRQINIT, (byte *) Txhdr);
  120.  
  121.         /* Fall through */
  122.  
  123.     case NOTHING_TO_DO:
  124.  
  125.         Rxtimeout = 200;
  126.         if (ZS_GetReceiverInfo () == ERROR)
  127.         {
  128.             XON_DISABLE ();
  129.             CLEAR_OUTBOUND ();
  130.             CLEAR_INBOUND ();
  131.             XON_ENABLE ();
  132.  
  133.             return FALSE;
  134.         }
  135.     }
  136.  
  137.     Rxtimeout = (int) (614400L / (long) cur_baud.rate_value);
  138.  
  139.     if (Rxtimeout < 400)
  140.         Rxtimeout = 400;
  141.  
  142.     if (fname == NULL)
  143.         goto Done;
  144.  
  145.     /*--------------------------------------------------------------------*/
  146.     /* Prepare the file for transmission.  Just ignore file open errors   */
  147.     /* because there may be other files that can be sent.                 */
  148.     /*--------------------------------------------------------------------*/
  149.  
  150.     Filename = fname;
  151.     CLEAR_IOERR ();
  152.     if ((Infile = share_fopen (Filename, read_binary, DENY_WRITE)) == NULL)
  153.     {
  154.         (void) got_error (MSG_TXT (M_OPEN_MSG), Filename);
  155.         rc = OK;
  156.         goto Done;
  157.     }
  158.  
  159.     if (isatty (fileno (Infile)))
  160.     {
  161.         errno = 1;
  162.         (void) got_error (MSG_TXT (M_DEVICE_MSG), Filename);
  163.         rc = OK;
  164.         goto Done;
  165.     }
  166.  
  167.     /*--------------------------------------------------------------------*/
  168.     /* Send the file                                                      */
  169.     /* Display outbound filename, size, and ETA for sysop                 */
  170.     /*--------------------------------------------------------------------*/
  171.  
  172.     (void) stat (Filename, &f);
  173.  
  174.     ltemp = (f.st_size * 10L / cur_baud.rate_value + 53L) / 54L;
  175.     (void) sprintf (j, "Z-Send %s, %ldb, %ld min.", Filename, f.st_size, ltemp);
  176.     file_length = f.st_size;
  177.  
  178.     if (un_attended && fullscreen)
  179.     {
  180.         clear_filetransfer ();
  181.         sb_move (filewin, 1, 2);
  182.         sb_puts (filewin, j);
  183.         elapse_time ();
  184.         (void) sprintf (j, "%3ld min", ltemp);
  185.         sb_move (filewin, 2, 69);
  186.         sb_puts (filewin, j);
  187.         sb_show ();
  188.     }
  189.     else
  190.     {
  191.         (void) printf ("%s", j);
  192. #if defined __IBMC__
  193.         fflush(stdout) ;
  194. #endif
  195.         set_xy (NULL);
  196.         locate_x += 2;
  197.     }
  198.  
  199.     /*--------------------------------------------------------------------*/
  200.     /* Get outgoing file name; no directory path, lower case              */
  201.     /*--------------------------------------------------------------------*/
  202.  
  203. #ifndef NEW_PATH_STUFF
  204.     for (p = (byte *) ((alias != NULL) ? alias : Filename), q = Txbuf; *p;)
  205.     {
  206.         if ((*p == '/') || (*p == '\\') || (*p == ':'))
  207.             q = Txbuf;
  208.         else
  209.             *q++ = (char) tolower (*p);
  210.  
  211.         p++;
  212.     }
  213.  
  214.     *q++ = '\0';
  215.     p = q;
  216. #else
  217.     p = ZMdmFlNmCndtn (Txbuf,
  218.         ((alias != NULL) ? alias : Filename),
  219.         NULL,
  220.         0);
  221.     p += strlen (p);
  222.     q = ++p;
  223. #endif
  224.  
  225.     /*--------------------------------------------------------------------*/
  226.     /* Zero out remainder of file header packet                           */
  227.     /*--------------------------------------------------------------------*/
  228.  
  229.     while (q < (Txbuf + KSIZE))
  230.         *q++ = '\0';
  231.  
  232.     /*--------------------------------------------------------------------*/
  233.     /* Store filesize, time last modified, and file mode in header packet */
  234.     /*--------------------------------------------------------------------*/
  235.  
  236. #ifdef ANSI_TIME_T
  237.     filetime = f.st_mtime - ANSI_TIME_T_DELTA;
  238. #else
  239.     filetime = f.st_mtime;
  240. #endif
  241.     (void) sprintf ((char *) p, "%lu %lo %o", f.st_size, filetime, f.st_mode);
  242.  
  243.     /*--------------------------------------------------------------------*/
  244.     /* Transmit the filename block and { the download                      */
  245.     /*--------------------------------------------------------------------*/
  246.  
  247.     throughput (0, 0L);
  248.  
  249.     /*--------------------------------------------------------------------*/
  250.     /* Check the results                                                  */
  251.     /*--------------------------------------------------------------------*/
  252.  
  253.     switch (ZS_SendFile (1 + strlen ((char *) p) + (int) (p - Txbuf), wazoo))
  254.     {
  255.     case ERROR:
  256.  
  257.         /*--------------------------------------------------*/
  258.         /* Something tragic happened                        */
  259.         /*--------------------------------------------------*/
  260.  
  261.         goto Err_Out;
  262.  
  263.     case OK:
  264.  
  265.         /*--------------------------------------------------*/
  266.         /* File was sent                                    */
  267.         /*--------------------------------------------------*/
  268.  
  269.         CLEAR_IOERR ();
  270.         (void) fclose (Infile);
  271.         Infile = NULL;
  272.         goto Done;
  273.  
  274.     case ZSKIP:
  275.  
  276.         status_line (MSG_TXT (M_REMOTE_REFUSED), Filename);
  277.  
  278.         /* Backwards compatibility for a while */
  279.  
  280.         rc = SPEC_COND;            /* Success but don't truncate! */
  281.         goto Done;
  282.  
  283.     default:
  284.  
  285.         /*--------------------------------------------------*/
  286.         /* Ignore the problem, get next file, trust other   */
  287.         /* error handling mechanisms to deal with problems  */
  288.         /*--------------------------------------------------*/
  289.  
  290.         goto Done;
  291.     }                            /* switch */
  292.  
  293. Err_Out:
  294.  
  295.     rc = FALSE;
  296.  
  297. Done:
  298.  
  299.     if (Infile)
  300.         (void) fclose (Infile);
  301.  
  302.     if (fsent < 0)
  303.         ZS_EndSend ();
  304.  
  305.     XON_DISABLE ();
  306.     XON_ENABLE ();
  307.  
  308.     return rc;
  309. }                                /* send_Zmodem */
  310.  
  311. /*--------------------------------------------------------------------------*/
  312. /* ZS SEND BINARY HEADER                                                    */
  313. /* Send ZMODEM binary header hdr of type type                               */
  314. /*--------------------------------------------------------------------------*/
  315.  
  316. static void LOCALFUNC 
  317. ZS_SendBinaryHeader (unsigned short type, register byte * hdr)
  318. {
  319.     register unsigned short crc;
  320.     int n;
  321.  
  322. #ifdef DEBUG
  323.     show_debug_name ("ZS_SendBinaryHeader");
  324. #endif
  325.  
  326.     BUFFER_BYTE (ZPAD);
  327.     BUFFER_BYTE (ZDLE);
  328.  
  329.     if ((Crc32t = Txfcs32) != 0)
  330.         ZS_32SendBinaryHeader (type, hdr);
  331.     else
  332.     {
  333.         BUFFER_BYTE (ZBIN);
  334.         ZS_SendByte ((byte) type);
  335.  
  336.         crc = Z_UpdateCRC (type, 0);
  337.  
  338.         for (n = 4; --n >= 0;)
  339.         {
  340.             ZS_SendByte (*hdr);
  341.             crc = Z_UpdateCRC (((unsigned short) (*hdr++)), crc);
  342.         }
  343.         ZS_SendByte ((byte) (crc >> 8));
  344.         ZS_SendByte ((byte) crc);
  345.  
  346.         UNBUFFER_BYTES ();
  347.     }
  348.  
  349.     if (type != ZDATA)
  350.     {
  351.         while (CARRIER && !OUT_EMPTY ())
  352.             time_release ();
  353.         if (!CARRIER)
  354.             CLEAR_OUTBOUND ();
  355.     }
  356. }                                /* ZS_SendBinaryHeader */
  357.  
  358. /*--------------------------------------------------------------------------*/
  359. /* ZS SEND BINARY HEADER                                                    */
  360. /* Send ZMODEM binary header hdr of type type                               */
  361. /*--------------------------------------------------------------------------*/
  362.  
  363. static void LOCALFUNC 
  364. ZS_32SendBinaryHeader (unsigned short type, register byte * hdr)
  365. {
  366.     unsigned long crc;
  367.     int n;
  368.  
  369. #ifdef DEBUG
  370.     show_debug_name ("ZS_32SendBinaryHeader");
  371. #endif
  372.  
  373.     BUFFER_BYTE (ZBIN32);
  374.     ZS_SendByte ((byte) type);
  375.  
  376.     crc = 0xFFFFFFFF;
  377.     crc = Z_32UpdateCRC (type, crc);
  378.  
  379.     for (n = 4; --n >= 0;)
  380.     {
  381.         ZS_SendByte (*hdr);
  382.         crc = Z_32UpdateCRC (((unsigned short) (*hdr++)), crc);
  383.     }
  384.  
  385.     crc = ~crc;
  386.     for (n = 4; --n >= 0;)
  387.     {
  388.         ZS_SendByte ((byte) crc);
  389.         crc >>= 8;
  390.     }
  391.  
  392.     UNBUFFER_BYTES ();
  393. }                                /* ZS_SendBinaryHeader */
  394.  
  395. /*--------------------------------------------------------------------------*/
  396. /* ZS SEND DATA                                                             */
  397. /* Send binary array buf with ending ZDLE sequence frameend                 */
  398. /*--------------------------------------------------------------------------*/
  399.  
  400. static void LOCALFUNC 
  401. ZS_SendData (register byte * buf, int length, unsigned short frameend)
  402. {
  403.     register unsigned short crc;
  404.  
  405. #ifdef DEBUG
  406.     show_debug_name ("ZS_SendData");
  407. #endif
  408.  
  409.     if (Crc32t)
  410.         ZS_32SendData (buf, length, frameend);
  411.     else
  412.     {
  413.         crc = 0;
  414.         for (; --length >= 0;)
  415.         {
  416.             ZS_SendByte (*buf);
  417.             crc = Z_UpdateCRC (((unsigned short) (*buf++)), crc);
  418.         }
  419.  
  420.         BUFFER_BYTE (ZDLE);
  421.         BUFFER_BYTE ((unsigned char) frameend);
  422.         crc = Z_UpdateCRC (frameend, crc);
  423.         ZS_SendByte ((byte) (crc >> 8));
  424.         ZS_SendByte ((byte) crc);
  425.  
  426.         UNBUFFER_BYTES ();
  427.  
  428.     }
  429.  
  430.     if (frameend == ZCRCW)
  431.     {
  432.         SENDBYTE (XON);
  433.         while (CARRIER && !OUT_EMPTY ())
  434.             time_release ();
  435.         if (!CARRIER)
  436.             CLEAR_OUTBOUND ();
  437.     }
  438. }                                /* ZS_SendData */
  439.  
  440. /*--------------------------------------------------------------------------*/
  441. /* ZS SEND DATA with 32 bit CRC                                             */
  442. /* Send binary array buf with ending ZDLE sequence frameend                 */
  443. /*--------------------------------------------------------------------------*/
  444.  
  445. static void LOCALFUNC 
  446. ZS_32SendData (register byte * buf, int length, unsigned short frameend)
  447. {
  448.     unsigned long crc;
  449.  
  450. #ifdef DEBUG
  451.     show_debug_name ("ZS_32SendData");
  452. #endif
  453.  
  454.     crc = 0xFFFFFFFF;
  455.     for (; --length >= 0; ++buf)
  456.     {
  457.         ZS_SendByte (*buf);
  458.         crc = Z_32UpdateCRC (((unsigned short) (*buf)), crc);
  459.     }
  460.  
  461.     BUFFER_BYTE (ZDLE);
  462.     BUFFER_BYTE ((unsigned char) frameend);
  463.     crc = Z_32UpdateCRC (frameend, crc);
  464.  
  465.     crc = ~crc;
  466.  
  467.     for (length = 4; --length >= 0;)
  468.     {
  469.         ZS_SendByte ((byte) crc);
  470.         crc >>= 8;
  471.     }
  472.  
  473.     UNBUFFER_BYTES ();
  474. }                                /* ZS_SendData */
  475.  
  476. /*--------------------------------------------------------------------------*/
  477. /* ZS SEND BYTE                                                             */
  478. /* Send character c with ZMODEM escape sequence encoding.                   */
  479. /* Escape XON, XOFF. Escape CR following @ (Telenet net escape)             */
  480. /*--------------------------------------------------------------------------*/
  481.  
  482. static void LOCALFUNC 
  483. ZS_SendByte (register byte c)
  484. {
  485.     static byte lastsent;
  486.  
  487.     switch (c)
  488.     {
  489.     case 015:
  490.     case 0215:
  491.  
  492.         if ((lastsent & 0x7F) != '@')
  493.             goto SendIt;
  494.  
  495.         /* else fall through */
  496.  
  497.     case 020:
  498.     case 021:
  499.     case 023:
  500.     case 0220:
  501.     case 0221:
  502.     case 0223:
  503.     case ZDLE:
  504.  
  505.         /*--------------------------------------------------*/
  506.         /* Quoted characters                                */
  507.         /*--------------------------------------------------*/
  508.  
  509.         BUFFER_BYTE (ZDLE);
  510.         c ^= 0x40;
  511.  
  512.         /* Then fall through */
  513.  
  514.     default:
  515.  
  516.         /*--------------------------------------------------*/
  517.         /* Normal character output                          */
  518.         /*--------------------------------------------------*/
  519.  
  520. SendIt:
  521.  
  522.         BUFFER_BYTE (lastsent = c);
  523.  
  524.     }                            /* switch */
  525. }                                /* ZS_SendByte */
  526.  
  527. /*--------------------------------------------------------------------------*/
  528. /* ZS GET RECEIVER INFO                                                     */
  529. /* Get the receiver's init parameters                                       */
  530. /*--------------------------------------------------------------------------*/
  531.  
  532. static int LOCALFUNC 
  533. ZS_GetReceiverInfo ()
  534. {
  535.     int n;
  536.  
  537. #ifdef DEBUG
  538.     show_debug_name ("ZS_GetReceiverInfo");
  539. #endif
  540.  
  541.     for (n = 10; --n >= 0;)
  542.     {
  543.         switch (Z_GetHeader ((byte *) Rxhdr))
  544.         {
  545.         case ZCHALLENGE:
  546.  
  547.             /*--------------------------------------*/
  548.             /* Echo receiver's challenge number     */
  549.             /*--------------------------------------*/
  550.  
  551.             Z_PutLongIntoHeader (Rxpos);
  552.             Z_SendHexHeader (ZACK, (byte *) Txhdr);
  553.             continue;
  554.  
  555.         case ZCOMMAND:
  556.  
  557.             /*--------------------------------------*/
  558.             /* They didn't see our ZRQINIT          */
  559.             /*--------------------------------------*/
  560.  
  561.             Z_PutLongIntoHeader (0L);
  562.             Z_SendHexHeader (ZRQINIT, (byte *) Txhdr);
  563.             continue;
  564.  
  565.         case ZRINIT:
  566.  
  567.             /*--------------------------------------*/
  568.             /*                                      */
  569.             /*--------------------------------------*/
  570.  
  571.             Rxflags = 0377 & Rxhdr[ZF0];
  572.             Rxbuflen = ((word) Rxhdr[ZP1] << 8) | Rxhdr[ZP0];
  573.             Txfcs32 = Rxflags & CANFC32;
  574.             return OK;
  575.  
  576.         case ZCAN:
  577.         case RCDO:
  578.         case TIMEOUT:
  579.  
  580.             return ERROR;
  581.  
  582.         case ZRQINIT:
  583.  
  584.             if (Rxhdr[ZF0] == ZCOMMAND)
  585.                 continue;
  586.  
  587.             /* else fall through */
  588.  
  589.         default:
  590.  
  591.             Z_SendHexHeader (ZNAK, (byte *) Txhdr);
  592.             continue;
  593.         }                        /* switch */
  594.     }                            /* for */
  595.  
  596.     return ERROR;
  597. }                                /* ZS_GetReceiverInfo */
  598.  
  599. /*--------------------------------------------------------------------------*/
  600. /* ZS SEND FILE                                                             */
  601. /* Send ZFILE frame and begin sending ZDATA frame                           */
  602. /*--------------------------------------------------------------------------*/
  603.  
  604. static int LOCALFUNC 
  605. ZS_SendFile (int blen, int wazoo)
  606. {
  607.     register int c;
  608.     long t;
  609.  
  610. #ifdef DEBUG
  611.     show_debug_name ("ZS_SendFile");
  612. #endif
  613.  
  614.     for (;;)
  615.     {
  616.         if (got_ESC ())
  617.         {
  618.             CLEAR_OUTBOUND ();
  619.             XON_DISABLE ();            /* Make sure xmitter is unstuck */
  620.             send_can ();            /* transmit at least 10 cans    */
  621.             t = timerset (200);        /* wait no more than 2 seconds  */
  622.  
  623.             while (!timeup (t) && !OUT_EMPTY () && CARRIER)
  624.                 time_release ();    /* Give up slice while waiting  */
  625.  
  626.             XON_ENABLE ();            /* Turn XON/XOFF back on...     */
  627.             z_log (MSG_TXT (M_KBD_MSG));
  628.             return ERROR;
  629.         }
  630.         else if (!CARRIER)
  631.             return ERROR;
  632.  
  633.         Txhdr[ZF0] = LZCONV;        /* Default file conversion mode */
  634.         Txhdr[ZF1] = LZMANAG;        /* Default file management mode */
  635.         Txhdr[ZF2] = LZTRANS;        /* Default file transport mode  */
  636.         Txhdr[ZF3] = 0;
  637.         ZS_SendBinaryHeader (ZFILE, (byte *) Txhdr);
  638.         ZS_SendData (Txbuf, blen, ZCRCW);
  639.  
  640. Again:
  641.  
  642.         switch (c = Z_GetHeader ((byte *) Rxhdr))
  643.         {
  644.         case ZRINIT:
  645.  
  646.             while ((c = Z_GetByte (50)) > 0)
  647.                 if (c == ZPAD)
  648.                     goto Again;
  649.  
  650.             /* if we run out, Fall thru to */
  651.  
  652.         default:
  653.  
  654.             continue;
  655.  
  656.         case ZCAN:
  657.         case RCDO:
  658.         case TIMEOUT:
  659.         case ZFIN:
  660.         case ZFERR:
  661.         case ZABORT:
  662.  
  663.             return ERROR;
  664.  
  665.         case ZSKIP:
  666.  
  667.             /*-----------------------------------------*/
  668.             /* Other system wants to skip this file    */
  669.             /*-----------------------------------------*/
  670.  
  671.             return c;
  672.  
  673.         case ZRPOS:
  674.  
  675.             /*-----------------------------------------*/
  676.             /* Resend from this position...            */
  677.             /*-----------------------------------------*/
  678.  
  679.             (void) fseek (Infile, Rxpos, SEEK_SET);
  680.             if (Rxpos != 0L)
  681.             {
  682.                 status_line (MSG_TXT (M_SYNCHRONIZING_OFFSET), Rxpos);
  683.                 CLEAR_OUTBOUND ();        /* Get rid of queued data */
  684.                 XON_DISABLE ();            /* End XON/XOFF restraint */
  685.                 SENDBYTE (XON);            /* Send XON to remote     */
  686.                 XON_ENABLE ();            /* Start XON/XOFF again   */
  687.             }
  688.             LastZRpos = Strtpos = Txpos = Rxpos;
  689.             ZRPosCount = 10;
  690.             CLEAR_INBOUND ();
  691.             return ZS_SendFileData (wazoo);
  692.         }                        /* switch */
  693.     }                            /* while */
  694. }                                /* ZS_SendFile */
  695.  
  696. /*--------------------------------------------------------------------------*/
  697. /* ZS SEND FILE DATA                                                        */
  698. /* Send the data in the file                                                */
  699. /*--------------------------------------------------------------------------*/
  700.  
  701. static int LOCALFUNC 
  702. ZS_SendFileData (int wazoo)
  703. {
  704.     register int c, e;
  705.     unsigned long ulrate;
  706.     char j[100];
  707.     word newcnt;
  708.     word blklen;
  709.     word maxblklen;
  710.     word goodblks = 0;
  711.     word goodneeded = 1;
  712.     long lSize, lTime;
  713.  
  714.     long t;
  715.  
  716. #ifdef DEBUG
  717.     show_debug_name ("ZS_SendFileData");
  718. #endif
  719.     ulrate = cur_baud.rate_value;
  720.  
  721.     maxblklen = (ulrate >= 9600) ? WAZOOMAX :
  722.         ((ulrate < 300) ? 128 : (int)ulrate / 300 * 256);
  723.  
  724.     if (maxblklen > WAZOOMAX)
  725.         maxblklen = WAZOOMAX;
  726.     if (!wazoo && maxblklen > KSIZE)
  727.         maxblklen = KSIZE;
  728.     if (Rxbuflen && maxblklen > (unsigned) Rxbuflen)
  729.         maxblklen = Rxbuflen;
  730.  
  731.     if (wazoo && (remote_capabilities & ZED_ZIPPER))
  732.         maxblklen = KSIZE;
  733.  
  734.     blklen = (fstblklen != 0) ? fstblklen : maxblklen;
  735.     goodneeded = (fstblklen != 0) ? 8 : 1;
  736.  
  737. SomeMore:
  738.  
  739.     if (CHAR_AVAIL ())
  740.     {
  741. WaitAck:
  742.  
  743.         switch (c = ZS_SyncWithReceiver (1))
  744.         {
  745.         case ZSKIP:
  746.  
  747.             /*-----------------------------------------*/
  748.             /* Skip this file                          */
  749.             /*-----------------------------------------*/
  750.  
  751.             return c;
  752.  
  753.         case ZACK:
  754.  
  755.             break;
  756.  
  757.         case ZRPOS:
  758.  
  759.             /*-----------------------------------------*/
  760.             /* Resume at this position                 */
  761.             /*-----------------------------------------*/
  762.  
  763.             blklen = ((blklen >> 2) > 64) ? blklen >> 2 : 64;
  764.             goodblks = 0;
  765.             goodneeded = ((goodneeded << 1) > 16) ? 16 : goodneeded << 1;
  766.             break;
  767.  
  768.         case ZRINIT:
  769.  
  770.             /*-----------------------------------------*/
  771.             /* Receive init                            */
  772.             /*-----------------------------------------*/
  773.  
  774.             goto file_sent;
  775.  
  776.         case TIMEOUT:
  777.  
  778.             /*-----------------------------------------*/
  779.             /* Timed out on message from other side    */
  780.             /*-----------------------------------------*/
  781.  
  782.             break;
  783.  
  784.         default:
  785.  
  786.             z_log (MSG_TXT (M_CAN_MSG));
  787.             (void) fclose (Infile);
  788.             return ERROR;
  789.         }                        /* switch */
  790.  
  791.         /*
  792.        * Noise probably got us here. Odds of surviving are not good. But we
  793.        * have to get unstuck in any event.
  794.        *
  795.        */
  796.  
  797.         Z_UncorkTransmitter ();    /* Get our side free if need be      */
  798.         SENDBYTE (XON);            /* Send an XON to release other side */
  799.  
  800.         while (CHAR_AVAIL ())
  801.         {
  802.             switch (MODEM_IN ())
  803.             {
  804.             case CAN:
  805.             case RCDO:
  806.             case ZPAD:
  807.  
  808.                 goto WaitAck;
  809.             }                    /* switch */
  810.         }                        /* while */
  811.     }                            /* while */
  812.  
  813.     newcnt = Rxbuflen;
  814.     Z_PutLongIntoHeader (Txpos);
  815.     ZS_SendBinaryHeader (ZDATA, (byte *) Txhdr);
  816.  
  817.     do
  818.     {
  819.         if (got_ESC ())
  820.         {
  821.             CLEAR_OUTBOUND ();
  822.             XON_DISABLE ();            /* Make sure xmitter is unstuck */
  823.             send_can ();            /* transmit at least 10 cans    */
  824.             t = timerset (200);        /* wait no more than 2 seconds  */
  825.  
  826.             while (!timeup (t) && !OUT_EMPTY () && CARRIER)
  827.                 time_release ();    /* Give up slice while waiting  */
  828.  
  829.             XON_ENABLE ();            /* Turn XON/XOFF back on...     */
  830.             z_log (MSG_TXT (M_KBD_MSG));
  831.             goto oops;
  832.         }
  833.  
  834.         if (!CARRIER)
  835.             goto oops;
  836.  
  837.         if ((unsigned) (c = fread (Txbuf, 1, blklen, Infile)) != z_size)
  838.         {
  839.             if (fullscreen && un_attended)
  840.             {
  841.                 sb_move (filewin, 2, 12);
  842.                 sb_puts (filewin, ultoa (((unsigned long) (z_size = c)), e_input, 10));
  843.                 sb_puts (filewin, "    ");
  844.                 elapse_time ();
  845.                 sb_show ();
  846.             }
  847.             else
  848.             {
  849.                 gotoxy (locate_x + 10, locate_y);
  850.                 (void) cputs (ultoa (((unsigned long) (z_size = c)), e_input, 10));
  851.                 (void) putch (' ');
  852.             }
  853.         }
  854.  
  855.         if ((unsigned) c < blklen)
  856.             e = ZCRCE;
  857.         else if (Rxbuflen && (newcnt -= c) <= 0)
  858.             e = ZCRCW;
  859.         else
  860.             e = ZCRCG;
  861.  
  862.         ZS_SendData (Txbuf, c, (unsigned short) e);
  863.  
  864.         (void) sprintf (j, "%3ld min",
  865.             ((file_length - Txpos) * 10L / ulrate + 53L) / 54L);
  866.  
  867.         if (fullscreen && un_attended)
  868.         {
  869.             sb_move (filewin, 2, 2);
  870.             sb_puts (filewin, ultoa (((unsigned long) Txpos), e_input, 10));
  871.             sb_puts (filewin, "  ");
  872.             sb_move (filewin, 2, 69);
  873.             sb_puts (filewin, j);
  874.             elapse_time ();
  875.             sb_show ();
  876.         }
  877.         else
  878.         {
  879.             gotoxy (locate_x, locate_y);
  880.             (void) cputs (ultoa (((unsigned long) Txpos), e_input, 10));
  881.             (void) putch (' ');
  882.             (void) putch (' ');
  883.             gotoxy (locate_x + 20, locate_y);
  884.             (void) printf ("%s", j);
  885.             (void) putch (' ');
  886. #if defined __IBMC__
  887.         fflush(stdout) ;
  888. #endif
  889.         }
  890.  
  891.         Txpos += c;
  892.         if (blklen < maxblklen && ++goodblks > goodneeded)
  893.         {
  894.             blklen = ((word) (blklen << 1) < maxblklen) ? blklen << 1 : maxblklen;
  895.             goodblks = 0;
  896.         }
  897.  
  898.         if (e == ZCRCW)
  899.             goto WaitAck;
  900.  
  901.         while (CHAR_AVAIL ())
  902.         {
  903.             switch (MODEM_IN ())
  904.             {
  905.             case CAN:
  906.             case RCDO:
  907.             case ZPAD:
  908.  
  909.                 /*--------------------------------------*/
  910.                 /* Interruption detected;               */
  911.                 /* stop sending and process complaint   */
  912.                 /*--------------------------------------*/
  913.  
  914.                 z_message (MSG_TXT (M_TROUBLE));
  915.                 CLEAR_OUTBOUND ();
  916.                 ZS_SendData (Txbuf, 0, ZCRCE);
  917.                 goto WaitAck;
  918.             }                    /* switch */
  919.         }                        /* while */
  920.  
  921.     }                            /* do */
  922.     while (e == ZCRCG);
  923.  
  924.     for (;;)
  925.     {
  926.         Z_PutLongIntoHeader (Txpos);
  927.         ZS_SendBinaryHeader (ZEOF, (byte *) Txhdr);
  928.  
  929.         switch (ZS_SyncWithReceiver (7))
  930.         {
  931.         case ZACK:
  932.  
  933.             continue;
  934.  
  935.         case ZRPOS:
  936.  
  937.             /*-----------------------------------------*/
  938.             /* Resume at this position...              */
  939.             /*-----------------------------------------*/
  940.  
  941.             goto SomeMore;
  942.  
  943.         case ZRINIT:
  944.  
  945.             /*-----------------------------------------*/
  946.             /* Receive init                            */
  947.             /*-----------------------------------------*/
  948.  
  949. file_sent:
  950.             if (locate_y && !(fullscreen && un_attended))
  951.                 gotoxy (2, (byte) locate_y - 1);
  952.  
  953.             lSize = Txpos - Strtpos;
  954.             lTime = throughput (1, Txpos - Strtpos);
  955.             status_line ("%s-Z%s %s", MSG_TXT (M_FILE_SENT), Crc32t ? "/32" : "", Filename);
  956.             update_files (1, Filename, lSize, lTime, 0);
  957.             return OK;
  958.  
  959.         case ZSKIP:
  960.  
  961.             /*-----------------------------------------*/
  962.             /* Request to skip the current file        */
  963.             /*-----------------------------------------*/
  964.  
  965.             z_log (MSG_TXT (M_SKIP_MSG));
  966.             CLEAR_IOERR ();
  967.             (void) fclose (Infile);
  968.             return c;
  969.  
  970.         default:
  971. oops:
  972.             z_log (MSG_TXT (M_CAN_MSG));
  973.             (void) fclose (Infile);
  974.             return ERROR;
  975.         }                        /* switch */
  976.     }                            /* while */
  977. }                                /* ZS_SendFileData */
  978.  
  979. /*--------------------------------------------------------------------------*/
  980. /* ZS SYNC WITH RECEIVER                                                    */
  981. /* Respond to receiver's complaint, get back in sync with receiver          */
  982. /*--------------------------------------------------------------------------*/
  983.  
  984. static int LOCALFUNC 
  985. ZS_SyncWithReceiver (int num_errs)
  986. {
  987.     register int c;
  988.     char j[50];
  989.  
  990. #ifdef DEBUG
  991.     show_debug_name ("ZS_SyncWithReceiver");
  992. #endif
  993.  
  994.     for (;;)
  995.     {
  996.         c = Z_GetHeader ((byte *) Rxhdr);
  997.         CLEAR_INBOUND ();
  998.         switch (c)
  999.         {
  1000.         case TIMEOUT:
  1001.  
  1002.             z_message (MSG_TXT (M_TIMEOUT));
  1003.             if ((num_errs--) >= 0)
  1004.                 break;
  1005.  
  1006.             /* else fall through */
  1007.  
  1008.         case ZCAN:
  1009.         case ZABORT:
  1010.         case ZFIN:
  1011.         case RCDO:
  1012.  
  1013.             z_log (MSG_TXT (M_ERROR));
  1014.             return ERROR;
  1015.  
  1016.         case ZRPOS:
  1017.  
  1018.             if (Rxpos == LastZRpos)        /* Same as last time?    */
  1019.             {
  1020.                 if (!(--ZRPosCount))    /* Yup, 10 times yet?    */
  1021.                     return ERROR;        /* Too many, get out     */
  1022.             }
  1023.             else
  1024.                 ZRPosCount = 10;        /* Reset repeat count    */
  1025.             LastZRpos = Rxpos;            /* Keep track of this    */
  1026.  
  1027.             rewind (Infile);            /* In case file EOF seen */
  1028.             (void) fseek (Infile, Rxpos, SEEK_SET);
  1029.             Txpos = Rxpos;
  1030.             (void) sprintf (j, MSG_TXT (M_RESENDING_FROM),
  1031.                 ultoa (((unsigned long) (Txpos)), e_input, 10));
  1032.             z_message (j);
  1033.             return c;
  1034.  
  1035.         case ZSKIP:
  1036.  
  1037.             z_log (MSG_TXT (M_SKIP_MSG));
  1038.  
  1039.             /* fall through */
  1040.  
  1041.         case ZRINIT:
  1042.  
  1043.             CLEAR_IOERR ();
  1044.             (void) fclose (Infile);
  1045.             return c;
  1046.  
  1047.         case ZACK:
  1048.  
  1049.             z_message (NULL);
  1050.             return c;
  1051.  
  1052.         default:
  1053.  
  1054.             z_message (IDUNNO_msg);
  1055.             ZS_SendBinaryHeader (ZNAK, (byte *) Txhdr);
  1056.             continue;
  1057.         }                        /* switch */
  1058.     }                            /* while */
  1059. }                                /* ZS_SyncWithReceiver */
  1060.  
  1061. /*--------------------------------------------------------------------------*/
  1062. /* ZS END SEND                                                              */
  1063. /* Say BIBI to the receiver, try to do it cleanly                           */
  1064. /*--------------------------------------------------------------------------*/
  1065.  
  1066. static void LOCALFUNC 
  1067. ZS_EndSend ()
  1068. {
  1069.  
  1070. #ifdef DEBUG
  1071.     show_debug_name ("ZS_EndSend");
  1072. #endif
  1073.  
  1074.     CLEAR_OUTBOUND ();
  1075.     CLEAR_INBOUND ();
  1076.  
  1077.     for (;;)
  1078.     {
  1079.         Z_PutLongIntoHeader (0L);
  1080.         ZS_SendBinaryHeader (ZFIN, (byte *) Txhdr);
  1081.  
  1082.         switch (Z_GetHeader ((byte *) Rxhdr))
  1083.         {
  1084.         case ZFIN:
  1085.  
  1086.             SENDBYTE ('O');
  1087.             SENDBYTE ('O');
  1088.  
  1089.             while (CARRIER && !OUT_EMPTY ())
  1090.                 time_release ();
  1091.             if (!CARRIER)
  1092.                 CLEAR_OUTBOUND ();
  1093.  
  1094.             /* fallthrough... */
  1095.  
  1096.         case ZCAN:
  1097.         case RCDO:
  1098.         case TIMEOUT:
  1099.  
  1100.             return;
  1101.         }                        /* switch */
  1102.     }                            /* while */
  1103. }                                /* ZS_EndSend */
  1104.