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