home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / MISC / LO241SRV.ZIP / ZSEND.C < prev   
C/C++ Source or Header  |  1998-05-17  |  32KB  |  1,034 lines

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