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