home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / os2tools / bnklysrc / f_send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-05  |  33.3 KB  |  999 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software <no-Inc>                   */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          No-Cost<no-tm> Software.                       */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*  Copyright (C) 1987, 1988, 1989 by Robert Hartman and Vincent Perriello  */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*        GENERAL PURPOSE FILE TRANSMITTER (Xmodem/YModem/Sealink)          */
  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.210.    */
  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 THE AUTHORS    */
  24. /*    AT THE  ADDRESSES LISTED BELOW.  IN NO EVENT SHOULD YOU PROCEED TO    */
  25. /*    USE   THIS  FILE  WITHOUT  HAVING   ACCEPTED  THE  TERMS  OF   THE    */
  26. /*    BINKLEYTERM  LICENSING AGREEMENT,  OR SUCH OTHER  AGREEMENT AS YOU    */
  27. /*    ARE ABLE TO REACH WITH THE AUTHORS.                                   */
  28. /*                                                                          */
  29. /*                                                                          */
  30. /*    The Authors can be reached at the following addresses:                */
  31. /*                                                                          */
  32. /*    Robert C. Hartman                      Vincent E. Perriello           */
  33. /*    Spark Software                         VEP Software                   */
  34. /*    427-3 Amherst Street                   111 Carroll Street             */
  35. /*    CS2032, Suite 232                      Naugatuck, CT 06770            */
  36. /*    Nashua, NH 03061                                                      */
  37. /*                                                                          */
  38. /*    FidoNet 1:132/101                      FidoNet 1:141/491              */
  39. /*    Data    (603) 888-8179                 Data    (203) 729-7569         */
  40. /*                                                                          */
  41. /*    Please feel free to contact us at any time to share your comments     */
  42. /*    about our software and/or licensing policies.                         */
  43. /*                                                                          */
  44. /*                                                                          */
  45. /*  This module is based largely on a similar module in OPUS-CBCS V1.03b.   */
  46. /*  The original work is (C) Copyright 1987, Wynn Wagner III. The original  */
  47. /*  author has graciously allowed us to use his code in this work.          */
  48. /*                                                                          */
  49. /*--------------------------------------------------------------------------*/
  50.  
  51. #include <sys\types.h>
  52. #include <sys\stat.h>
  53. #include <sys\timeb.h>
  54. #include <errno.h>
  55. #include <stdio.h>
  56. #include <time.h>
  57. #include <stdlib.h>
  58. #include <string.h>
  59. #include <io.h>
  60. #include <conio.h>
  61. #include <dos.h>
  62.  
  63. #ifdef __TURBOC__
  64. #include <alloc.h>
  65. #include <mem.h>
  66. #else
  67. #include <malloc.h>
  68. #include <memory.h>
  69. #endif
  70.  
  71.  
  72. #include "com.h"
  73. #include "xfer.h"
  74. #include "sbuf.h"
  75. #include "sched.h"
  76. #include "externs.h"
  77. #include "prototyp.h"
  78. #include "find.h"   /*PLF Fri  05-05-1989  23:23:05 */
  79.  
  80. static int send_ackless;
  81. static int ackless_ok;
  82. static char *NOACKS_msg = "SEAlink Overdrive Disengaged";
  83.  
  84. /*--------------------------------------------------------------------------*/
  85. /* MULTI-PURPOSE FILE TRANSFER                                              */
  86. /*--------------------------------------------------------------------------*/
  87. int send_file (fname, protocol)
  88. char *fname, protocol;
  89. {
  90.    register int i, j;
  91.    register byte *b;
  92.    static FSCAN *dh = NULL;    /*PLF Fri  05-05-1989  23:15:36 */
  93.    struct zero_block *header;
  94.    int in_char;
  95.    int in_char1;
  96.    long ackblock;
  97.    long blknum;
  98.    long last_block;
  99.    long temp;
  100.    unsigned int errs;
  101.    int real_errs;
  102.    int sliding;
  103.    int base;
  104.    int head;
  105.    int block_size;
  106.    char *buffer;
  107.    int do_chksum;
  108.    FILE *fp;
  109.    char *message;
  110.    long block_timer, timerset ();
  111.    int win_size;
  112.    int full_window;
  113.    int may_be_seadog;
  114.    int ackerr;
  115.    struct stat st_stat;
  116.    char junkbuff[80];
  117.  
  118.    if (protocol == 'F')
  119.       {
  120.       protocol = 'S';
  121.       may_be_seadog = 1;
  122.       }
  123.    else may_be_seadog = 0;
  124.    fp = NULL;
  125.    sliding = 0;
  126.    ackblock = -1;
  127.    do_chksum = errs = 0;
  128.    ackerr = 0;
  129.    real_errs = 0;
  130.  
  131.  
  132.    /*
  133.     * The following window size works out to be between 3.5 and 4.5 seconds
  134.     * of data at any valid baud rate.  This gives us a set time that the
  135.     * other end will wait before NAK'ing a block if it waits  to flush its
  136.     * buffer before NAK'ing.  If it does not wait, then it does not matter
  137.     * very much except to make sure we only have a set amount of run-ahead
  138.     * that will fit in a 4K buffer                   
  139.     */
  140.    full_window = cur_baud / 400;
  141.  
  142.    if (small_window && full_window > 6)
  143.       full_window = 6;
  144.  
  145.    XON_DISABLE ();
  146.  
  147.    /*--------------------------------------------------------------------*/
  148.    /* Prepare file                                                       */
  149.    /*--------------------------------------------------------------------*/
  150.    if ((!fname) || (!fname[0]))                  /* No file?  Just send an
  151.                                                   * EOT.       */
  152.       {
  153.  
  154.       CLEAR_INBOUND ();
  155.  
  156.       for (i = 0; i < 5; i++)
  157.          {
  158.          switch (in_char = TIMED_READ (5))
  159.             {
  160.  
  161.             case 'C':
  162.             case NAK:
  163.             case CAN:
  164.                SENDBYTE (EOT);
  165.                break;
  166.  
  167.             case TSYNC:
  168.                return TSYNC;
  169.  
  170.             default:
  171.                if (in_char < ' ')
  172.                   return 0;
  173.  
  174.             }                                    /* switch */
  175.          }
  176.       return 0;
  177.       }
  178.  
  179.    strlwr (fname);                               /* ww/870225 */
  180.    CLEAR_IOERR ();
  181.    if(!dh) dh = opendir();              /*PLF Fri  05-05-1989  23:16:37 */
  182.    if(!findfirst(fname, _A_NORMAL, dh)) /*PLF Fri  05-05-1989  23:17:09 */
  183.       fp = fopen (fname, read_binary);
  184.    else errno = ENOENT;
  185.  
  186.    if (got_error (OPEN_msg, fname))
  187.       {
  188.       send_can ();
  189.       return 0;
  190.       }
  191.    if (isatty (fileno (fp)))
  192.       {
  193.       errno = 1;
  194.       got_error (DEVICE_msg, fname);
  195.       fclose (fp);
  196.       return (NULL);
  197.       }
  198.  
  199.    /*--------------------------------------------------------------------*/
  200.    /* Prepare buffer                                                     */
  201.    /*--------------------------------------------------------------------*/
  202.    buffer = Txbuf;
  203.    header = (struct zero_block *) buffer;
  204.    if (!buffer)
  205.       {
  206.       message = MEMOVFL_msg;
  207.       goto fubar;
  208.       }
  209.  
  210.    /*--------------------------------------------------------------------*/
  211.    /* Prepare method                                                     */
  212.    /*--------------------------------------------------------------------*/
  213.    block_size = 128;
  214.    head = SOH;
  215.    switch (protocol)
  216.       {
  217.       case 'Y':
  218.          base = 1;
  219.          block_size = 1024;
  220.          head = STX;
  221.          break;
  222.       case 'X':
  223.          base = 1;
  224.          break;
  225.       case 'S':
  226.          base = 0;
  227.          break;
  228.       case 'T':
  229.          base = 0;
  230.          head = SYN;
  231.          break;
  232.       case 'M':
  233.          base = 1;
  234.          break;
  235.       default:
  236.          status_line ("!Protocol?");
  237.          return 0;
  238.       }
  239.    blknum = base;
  240.  
  241.    last_block = (long) ((dh->size + ((long) block_size - 1L)) / (long) block_size); /*PLF Fri  05-05-1989  23:17:40 */
  242.  
  243.    sprintf (junkbuff, "Send %s (%ld %c-blks)", fname, last_block, protocol);
  244.    if (un_attended && fullscreen)
  245.       {
  246.       clear_filetransfer ();
  247.       sb_move (filewin, 1, 2);
  248.       sb_puts (filewin, junkbuff);
  249.       sb_show ();
  250.       }
  251.    else
  252.       {
  253.       cprintf ("\r\n");
  254.       cprintf ("%s", junkbuff);
  255.       set_xy (NULL);
  256.       locate_x += 2;
  257.       }
  258.  
  259.  
  260.    /*--------------------------------------------------------------------*/
  261.    /* Wait for signal to begin                                           */
  262.    /*--------------------------------------------------------------------*/
  263.    do
  264.       {
  265.       i = TIMED_READ (5);
  266.       switch (i)
  267.          {
  268.          case NAK:
  269.             /*--------------------------------------------*/
  270.             /* NAK                                        */
  271.             /*--------------------------------------------*/
  272.             do_chksum = 1;
  273.             /* fallthrough */
  274.  
  275.          case 'C':
  276.             /*--------------------------------------------*/
  277.             /* CRC RESPONSE                               */
  278.             /*--------------------------------------------*/
  279.                {
  280.                int send_tmp;
  281.  
  282.                if (((send_tmp = TIMED_READ (1)) >= 0)
  283.            && (TIMED_READ (1) == ((~send_tmp) & 0xff)))
  284.                   {
  285.                   if (send_tmp <= 1)
  286.                      sliding = 1;
  287.                   else
  288.                      {
  289.                      /* Not a normal SEAlink startup    */
  290.                      /* Lets end the transmission and   */
  291.                      /* try again.  Nasty, but it helps */
  292.                      SENDBYTE (EOT);
  293.                      continue;
  294.                      }
  295.                   }
  296.                if (may_be_seadog)
  297.                   {
  298.                   sliding = 1;
  299.                   }
  300.                errs = 0;
  301.                CLEAR_INBOUND ();
  302.                throughput (0, 0L);
  303.                goto sendloop;
  304.                }
  305.  
  306.          case CAN:
  307.             /*--------------------------------------------*/
  308.             /* CANCEL                                     */
  309.             /*--------------------------------------------*/
  310.             message = CAN_msg;
  311.             goto fubar;
  312.  
  313.          default:
  314.             /*--------------------------------------------*/
  315.             /* OTHER RESPONSES (debris)                   */
  316.             /*--------------------------------------------*/
  317.             if (got_ESC ())
  318.                {
  319.                message = KBD_msg;
  320.                goto fubar;
  321.                }
  322.             else if ((errs++) > 15)
  323.                {
  324.                message = TIME_msg;
  325.                goto fubar;
  326.                }
  327.             block_timer = timerset (50);
  328.             while (!timeup (block_timer))
  329.                time_release ();
  330.             CLEAR_INBOUND ();
  331.  
  332.          }                                       /* switch */
  333.       }                                          /* wait for signal to begin */
  334.    while (CARRIER);
  335.  
  336.    message = CARRIER_msg;
  337.    goto fubar;
  338.  
  339.  
  340.    /*--------------------------------------------------------------------*/
  341.    /* Transfer                                                           */
  342.    /*--------------------------------------------------------------------*/
  343. sendloop:
  344.    while (CARRIER)
  345.       {
  346.       message = NULL;
  347.       win_size = (blknum < 2) ? 2 : (send_ackless ? 220 : full_window);
  348.  
  349.       if (got_ESC ())
  350.          {
  351.          message = KBD_msg;
  352.          goto fubar;
  353.          }
  354.  
  355.       if (blknum <= last_block)
  356.          {
  357.          /*--------------------------------------------------------*/
  358.          /* DATA                                                   */
  359.          /*--------------------------------------------------------*/
  360.          memset (buffer, 0, block_size);
  361.          if (blknum)
  362.             {
  363.             errno = 0;
  364.             fseek (fp, ((long) (blknum - 1) * (long) block_size), 0);
  365.             if (got_error (READ_msg, fname))
  366.                {
  367.                message = SEEK_msg;
  368.                goto fubar;
  369.                }
  370.  
  371.             errno = 0;
  372.             fread (buffer, block_size, 1, fp);
  373.             if (got_error (READ_msg, fname))
  374.                {
  375.                message = READ_msg;
  376.                goto fubar;
  377.                }
  378.             }
  379.          else
  380.             {
  381.             block_size = 128;
  382.             header->size = dh->size;    /*PLF Fri  05-05-1989  23:17:47 */
  383.             stat (fname, &st_stat);
  384.             tzset ();
  385.             header->time = st_stat.st_atime - timezone;
  386.  
  387.             stcgfn (header->name, dh->name);    /*PLF Fri  05-05-1989  23:17:55 */
  388.  
  389.             if (protocol == 'T')
  390.                {
  391.                for (i = 0; i < HEADER_NAMESIZE; i++)
  392.                   if (!(header->name[i]))
  393.                      header->name[i] = ' ';
  394.                header->time = findtime(dh); /*PLF Fri  05-05-1989  23:18:02 */
  395.                }
  396.  
  397.             strcpy (header->moi, xfer_id);
  398.             if ((cur_baud >= 9600) && (sliding))
  399.                {
  400.                header->noacks = 1;
  401.                send_ackless = 1;
  402.                }
  403.             else
  404.                {
  405.                header->noacks = 0;
  406.                send_ackless = 0;
  407.                }
  408.  
  409.             if (no_overdrive)
  410.                {
  411.                header->noacks = 0;
  412.                send_ackless = 0;
  413.                }
  414.  
  415.             ackless_ok = 0;
  416.             }
  417.  
  418.          /*--------------------------------------------------------*/
  419.          /* HEAD                                                   */
  420.          /*--------------------------------------------------------*/
  421.          SENDBYTE ((unsigned char) head);
  422.          SENDBYTE ((unsigned char) (blknum & 0xff));
  423.          SENDBYTE ((unsigned char) (~(blknum & 0xff)));
  424.  
  425.          /*--------------------------------------------------------*/
  426.          /* SEND                                                   */
  427.          /*--------------------------------------------------------*/
  428.          b = buffer;
  429.          SENDCHARS (b, block_size, 1);
  430.  
  431.          /*--------------------------------------------------------*/
  432.          /* CHECK                                                  */
  433.          /*--------------------------------------------------------*/
  434.          if ((do_chksum) || (head == SYN))
  435.             {
  436.             unsigned char chksum = '\0';
  437.  
  438.             for (b = buffer, i = 0; i < block_size; i++, b++)
  439.                chksum += (*b);
  440.             SENDBYTE (chksum);
  441.             }
  442.          else
  443.             {
  444.             word crc;
  445.  
  446.             for (b = buffer, crc = i = 0; i < block_size; i++, b++)
  447.                crc = xcrc (crc, (byte) (*b));
  448.  
  449.             SENDBYTE ((unsigned char) (crc >> 8));
  450.             SENDBYTE ((unsigned char) (crc & 0xff));
  451.             }
  452.          }                                       /* if not finished */
  453.  
  454.       /*
  455.        * Only wait 30 seconds for a response For non-sliding this number is
  456.        * updated, for sliding we have a problem since the output buffer may
  457.        * still have stuff in it. We need to make sure we reset this when
  458.        * output is done in the sliding case.  What we actually do is reset it
  459.        * if the output has not yet completed.  We only check it in the case
  460.        * of debris, then recycle, so this should be a reasonable way  of
  461.        * doing things in the sliding case. 
  462.        */
  463.       block_timer = timerset (3000);
  464.  
  465. slide_reply:
  466.  
  467.       /*
  468.        * If we are not sliding, force the output and purge the input. This is
  469.        * simply good Xmodem practice.  It is also necessary to make sure that
  470.        * the other end has received all of the data before starting the block
  471.        * reply timeout. 
  472.        */
  473.       if (!sliding)
  474.          {
  475.          while (!OUT_EMPTY ())
  476.             time_release ();
  477.          block_timer = timerset (3000);
  478.          }
  479.  
  480.       /*--------------------------------------------------------------*/
  481.       /* REPLY: Slide                                                 */
  482.       /* Don't wait, unless other end has something to say            */
  483.       /* or we're at/beyond the window.                               */
  484.       /*--------------------------------------------------------------*/
  485.       else if ((blknum < (ackblock + win_size)) &&      /* in window    */
  486.                (blknum < last_block) &&          /* have more to send  */
  487.                (PEEKBYTE () < 0)                 /* other end is quiet */
  488.          )
  489.          {
  490.          if ((send_ackless) && (blknum > 0))
  491.             {
  492.             ackblock = blknum;
  493.  
  494.             if (blknum >= last_block)
  495.                {
  496.                if (ackless_ok)
  497.                   {
  498.                   if (fullscreen && un_attended)
  499.                      {
  500.                      sb_move (filewin, 2, 2);
  501.                      sb_puts (filewin, ultoa (((unsigned long) (last_block)), e_input, 10));
  502.                      sb_putc (filewin, '*');
  503.                      sb_show ();
  504.                      }
  505.                   else
  506.                      {
  507.                      gotoxy (locate_x, locate_y);
  508.                      cputs (ultoa (((unsigned long) (last_block)), e_input, 10));
  509. /*PLF                bdos (9, (unsigned int) "*$", 0); */
  510.                      putch('*'); /*PLF Fri  05-05-1989  06:57:35 */
  511.                      }
  512.                   goto done;
  513.                   }
  514.  
  515.                blknum = last_block + 1;
  516.                goto sendloop;
  517.                }
  518.  
  519.             ++blknum;
  520.  
  521.             if (!(blknum & 0x001F))              /* Update SLO display every
  522.                                                   * 32 */
  523.                {
  524.                if (fullscreen && un_attended)
  525.                   {
  526.                   sb_move (filewin, 2, 2);
  527.                   sb_puts (filewin, ultoa (((unsigned long) (blknum)), e_input, 10));
  528.                   sb_putc (filewin, '*');
  529.                   sb_show ();
  530.                   }
  531.                else
  532.                   {
  533.                   gotoxy (locate_x, locate_y);
  534.                   cputs (ultoa (((unsigned long) (blknum)), e_input, 10));
  535. /*PLF             bdos (9, (unsigned int) "*$", 0); */
  536.                   putch('*'); /*PLF Fri  05-05-1989  06:57:35 */
  537.                   }
  538.                }
  539.             }
  540.          else
  541.             {
  542.             blknum++;
  543.             }
  544.          goto sendloop;
  545.          }
  546.  
  547.       if (PEEKBYTE () < 0)
  548.          {
  549.          if (send_ackless)
  550.             {
  551.             ackblock = blknum;
  552.  
  553.             if (blknum >= last_block)
  554.                {
  555.                if (ackless_ok)
  556.                   {
  557.                   if (fullscreen && un_attended)
  558.                      {
  559.                      sb_move (filewin, 2, 2);
  560.                      sb_puts (filewin, ultoa (((unsigned long) (last_block)), e_input, 10));
  561.                      sb_putc (filewin, '*');
  562.                      sb_show ();
  563.                      }
  564.                   else
  565.                      {
  566.                      gotoxy (locate_x, locate_y);
  567.                      cputs (ultoa (((unsigned long) (last_block)), e_input, 10));
  568. /*PLF                bdos (9, (unsigned int) "*$", 0); */
  569.                      putch('*'); /*PLF Fri  05-05-1989  06:57:35 */
  570.                      }
  571.                   goto done;
  572.                   }
  573.  
  574.                blknum = last_block + 1;
  575.                goto sendloop;
  576.                }
  577.  
  578.             ++blknum;
  579.  
  580.             if ((blknum % 20) == 0)
  581.                {
  582.                if (fullscreen && un_attended)
  583.                   {
  584.                   sb_move (filewin, 2, 2);
  585.                   sb_puts (filewin, ultoa (((unsigned long) (blknum)), e_input, 10));
  586.                   sb_putc (filewin, '*');
  587.                   sb_show ();
  588.                   }
  589.                else
  590.                   {
  591.                   gotoxy (locate_x, locate_y);
  592.                   cputs (ultoa (((unsigned long) (blknum)), e_input, 10));
  593. /*PLF             bdos (9, (unsigned int) "*$", 0); */
  594.                   putch('*'); /*PLF Fri  05-05-1989  06:57:35 */
  595.                   }
  596.                }
  597.  
  598.             goto sendloop;
  599.             }
  600.          }
  601.  
  602. reply:
  603.       /*--------------------------------------------------------------*/
  604.       /* REPLY: Wait state                                            */
  605.       /* No sliding, or slid too far.  Wait for a reply.              */
  606.       /* If we got here we are either not sliding, or we are sliding  */
  607.       /* and have received an input character, or we are sliding and  */
  608.       /* have slid too far.  In the first case the following loop     */
  609.       /* will not do anything because the output is empty, in the     */
  610.       /* second case we also will not do anything since we have an    */
  611.       /* input character ready, in the final case we want to execute  */
  612.       /* the loop since we are in a wait state.  The loop will go on  */
  613.       /* until the output is empty (in the worst case), and since we  */
  614.       /* we have disabled flow control here (right???) we will never  */
  615.       /* have to worry about the loop not terminating.  Now, we just  */
  616.       /* sit and loop as long as there is output to do and no input.  */
  617.       /* Just to make wwIII happy do a time_release() so that his     */
  618.       /* DDos system will be more efficient!                          */
  619.       /*--------------------------------------------------------------*/
  620.  
  621.       while ((!OUT_EMPTY ()) &&
  622.              (PEEKBYTE () < 0))
  623.          time_release ();                        /* ... time slice routine
  624.                                                   * for multi-taskers */
  625.  
  626.       /*--------------------------------------------------------------*/
  627.       /* If we got here we either sent all the output, or got input.  */
  628.       /* In the first case we should get a response within 15 seconds */
  629.       /* In the second case we should get an immediate response.      */
  630.       /* Either way, nothing in 30 seconds is a timeout               */
  631.       /*--------------------------------------------------------------*/
  632.       if ((in_char = TIMED_READ (30)) < 0)
  633.          {
  634.          message = TIME_msg;
  635.          goto fubar;
  636.          }
  637.  
  638.       if (in_char == 'C')
  639.          {
  640.          do_chksum = 0;
  641.          in_char = NAK;
  642.          }
  643.  
  644.       /*--------------------------------------------------------------*/
  645.       /* CAN                                                          */
  646.       /*--------------------------------------------------------------*/
  647.       if (in_char == CAN)
  648.          {
  649.          message = CAN_msg;
  650.          goto fubar;
  651.          }
  652.  
  653.       /*--------------------------------------------------------------*/
  654.       /* REPLY: Take action based on slide-response                   */
  655.       /*--------------------------------------------------------------*/
  656.       if ((in_char > 0) && (sliding))
  657.          {
  658.          if (++ackerr >= 10)
  659.             {
  660.             if (send_ackless)
  661.                {
  662.                send_ackless = 0;
  663.                message = NOACKS_msg;
  664.                }
  665.             }
  666.  
  667.          if ((in_char == ACK) || (in_char == NAK))
  668.             {
  669.             if ((i = TIMED_READ (2)) < 0)
  670.                {
  671.                sliding = 0;
  672.                if (send_ackless)
  673.                   {
  674.                   send_ackless = 0;
  675.                   message = NOACKS_msg;
  676.                   }
  677.                }
  678.             else
  679.                {
  680.                if ((j = TIMED_READ (2)) < 0)
  681.                   {
  682.                   sliding = 0;
  683.                   if (send_ackless)
  684.                      {
  685.                      send_ackless = 0;
  686.                      message = NOACKS_msg;
  687.                      }
  688.                   }
  689.                else if (i == (j ^ 0xff))
  690.                   {
  691.                   temp = blknum - ((blknum - i) & 0xff);
  692.                   if ((temp <= blknum) && (temp > (blknum - win_size - 10)))
  693.                      {
  694.                      if (in_char == ACK)
  695.                         {
  696.                         if ((head == SYN) && (blknum))
  697.                            head = SOH;           /* ZapTeLink */
  698.  
  699.                         if (send_ackless)
  700.                            {
  701.                            ackless_ok = 1;
  702.                            goto slide_reply;
  703.                            }
  704.                         else
  705.                            {
  706.                            ackblock = temp;
  707.                            }
  708.  
  709.                         blknum++;
  710.  
  711.                         if (ackblock >= last_block)
  712.                            {
  713.                            goto done;
  714.                            }
  715.                         errs = 0;
  716.                         }
  717.                      else
  718.                         {
  719.                         blknum = temp;
  720.                         /* CLEAR_INBOUND(); */
  721.                         CLEAR_OUTBOUND ();
  722.                         errs++;
  723.                         real_errs++;
  724.                         }
  725.                      }
  726.                   }
  727.                else
  728.                   {
  729.                   message = "SLIDE CMPL ERR";
  730.                   }
  731.                }
  732.             }
  733.          else
  734.             {
  735.             /*--------------------------------------------------*/
  736.             /* If we got debris, just ignore it and go on if we */
  737.             /* have not yet had a timeout.  If we timed out,    */
  738.             /* then just go to the fubar label and abort        */
  739.             /*--------------------------------------------------*/
  740.  
  741.             if (fullscreen && un_attended)
  742.                {
  743.                sb_move (filewin, 2, 12);
  744.                sb_puts (filewin, " Debris");
  745.                sb_show ();
  746.                }
  747.             else
  748.                {
  749.                gotoxy (locate_x + 10, locate_y);
  750.                cprintf (" Debris [%Xh]", in_char);
  751.                }
  752.  
  753.             /*--------------------------------------------------*/
  754.             /* The error is timeout with the output buffer      */
  755.             /* empty (we can't penalize someone for a timeout   */
  756.             /* if we haven't yet sent them all they need!!!     */
  757.             /*--------------------------------------------------*/
  758.  
  759.             if (timeup (block_timer) && OUT_EMPTY ())
  760.                {
  761.                message = TIME_msg;
  762.                goto fubar;
  763.                }
  764.  
  765.             /*--------------------------------------------------*/
  766.             /* Ok, we either have a timeout or the buffer still */
  767.             /* has stuff in it.  If it still has stuff, reset   */
  768.             /* the timeout variable before trying again         */
  769.             /*--------------------------------------------------*/
  770.  
  771.             else if (!OUT_EMPTY ())
  772.                block_timer = timerset (3000);
  773.  
  774.             goto slide_reply;
  775.             }
  776.          }
  777.  
  778.       /*--------------------------------------------------------------*/
  779.       /* REPLY: Take action based on regular response                 */
  780.       /*--------------------------------------------------------------*/
  781.       if (!sliding)
  782.          {
  783.          if (in_char == ACK)
  784.             {
  785.             /*--------------------------------------------------*/
  786.             /* On block 10, throw in an extra pause to give the */
  787.             /* other end a change to fall into a slide if it    */
  788.             /* feels it's something it needs to do.             */
  789.             /*--------------------------------------------------*/
  790.             if (blknum == 10)
  791.                timer (3);                        /* approx. 3/10s second */
  792.  
  793.             /*--------------------------------------------------*/
  794.             /* Smell the other system vis-a-vis a slide.        */
  795.             /*--------------------------------------------------*/
  796.             if (PEEKBYTE () > 0)
  797.                {
  798.                int send_tmp;
  799.  
  800.                if (((send_tmp = TIMED_READ (1)) >= 0)
  801.                    && (TIMED_READ (1) == ((~send_tmp) & 0xff)))
  802.                   {
  803.                   sliding = 1;
  804.                   ackblock = send_tmp;
  805.                   }
  806.                }
  807.  
  808.             message = NULL;
  809.             if (blknum >= last_block)
  810.                goto done;
  811.             blknum++;
  812.  
  813.             if ((head == SYN) && (blknum))
  814.                head = SOH;                       /* ZapTeLink */
  815.  
  816.             errs = 0;
  817.             }
  818.          else if (in_char == NAK)
  819.             {
  820.             errs++;
  821.             real_errs++;
  822.             timer (5);
  823.             CLEAR_OUTBOUND ();
  824.             message = NAK_msg;
  825.             }
  826.          else if (CARRIER)
  827.             {
  828.             /* Did we time out yet? */
  829.             if (!timeup (block_timer))
  830.                goto reply;
  831.             else
  832.                {
  833.                message = TIME_msg;
  834.                goto fubar;
  835.                }
  836.             }
  837.          else
  838.             {
  839.             message = CARRIER_msg;
  840.             goto fubar;
  841.             }
  842.          }
  843.  
  844.       if (errs > 10)
  845.          {
  846.          message = FUBAR_msg;
  847.          goto fubar;
  848.          }
  849.  
  850.       temp = (blknum <= last_block) ? blknum : last_block;
  851.       if (fullscreen && un_attended)
  852.          {
  853.          sb_move (filewin, 2, 2);
  854.          sb_puts (filewin, ultoa (((unsigned long) (temp)), e_input, 10));
  855.          sb_show ();
  856.          }
  857.       else
  858.          {
  859.          gotoxy (locate_x, locate_y);
  860.          cputs (ultoa (((unsigned long) (temp)), e_input, 10));
  861.          }
  862.  
  863.       if ((sliding) && (ackblock > 0))
  864.          {
  865.          if (send_ackless)
  866.             {
  867.             if (fullscreen && un_attended)
  868.                {
  869.                sb_putc (filewin, '*');
  870.                sb_show ();
  871.                }
  872.             else
  873.                {
  874. /*PLF          bdos (9, (unsigned int) "*$", 0); */
  875.                putch('*'); /*PLF Fri  05-05-1989  06:57:35 */
  876.                }
  877.             }
  878.          else
  879.             {
  880.             if (fullscreen && un_attended)
  881.                {
  882.                sb_puts (filewin, " : ");
  883.                sb_puts (filewin, ultoa (((unsigned long) (ackblock)), e_input, 10));
  884.                sb_show ();
  885.                }
  886.             else
  887.                {
  888. /*PLF          bdos (9, (unsigned int) " : $", 0); */
  889.                cputs(" : $"); /*PLF Fri  05-05-1989  07:37:42 */
  890.                cputs (ultoa (((unsigned long) (ackblock)), e_input, 10));
  891.                }
  892.             }
  893.          }
  894.  
  895.       if (message)
  896.          {
  897.          if (fullscreen && un_attended)
  898.             {
  899.             sb_putc (filewin, ' ');
  900.             sb_puts (filewin, message);
  901.             sb_puts (filewin, "                         ");
  902.             sb_show ();
  903.             }
  904.          else
  905.             {
  906.             putch (' ');
  907.             cputs (message);
  908.             cputs ("                         ");
  909.             }
  910.          }
  911.       }                                          /* while */
  912.  
  913.    message = CARRIER_msg;
  914.  
  915. fubar:
  916.  
  917.    CLEAR_OUTBOUND ();
  918.    send_can ();
  919.  
  920.    status_line ("!%s not sent: %s", fname, message);
  921.  
  922.    if (fp)
  923.       fclose (fp);
  924.  
  925.    return 0;
  926.  
  927. done:
  928.    while (!OUT_EMPTY ())
  929.       time_release ();
  930.  
  931.    CLEAR_INBOUND ();
  932.    SENDBYTE (EOT);
  933.  
  934.    ackerr = 1;
  935.    blknum = last_block + 1;
  936.  
  937.    for (i = 0; i < 5; i++)
  938.       {
  939.       if (!CARRIER)
  940.          {
  941.          ackerr = 1;
  942.          goto gohome;
  943.          }
  944.  
  945.       switch (TIMED_READ (5))
  946.          {
  947.          case 'C':
  948.          case NAK:
  949.          case CAN:
  950.             if (sliding && ((in_char = TIMED_READ (1)) >= 0))
  951.                {
  952.                in_char1 = TIMED_READ (1);
  953.                if (in_char == (in_char1 ^ 0xff))
  954.                   {
  955.                   blknum -= ((blknum - in_char) & 0xff);
  956.                   CLEAR_INBOUND ();
  957.                   if (blknum <= last_block)
  958.                      goto sendloop;
  959.                   }
  960.                }
  961.             CLEAR_INBOUND ();
  962.             SENDBYTE (EOT);
  963.             break;
  964.  
  965.          case TSYNC:
  966.             ackerr = TSYNC;
  967.             goto gohome;
  968.  
  969.          case ACK:
  970.             if (sliding && ((in_char = TIMED_READ (1)) >= 0))
  971.                {
  972.                in_char1 = TIMED_READ (1);
  973.                }
  974.             ackerr = 1;
  975.             goto gohome;
  976.  
  977.          }                                       /* switch */
  978.       }
  979.  
  980. gohome:
  981.  
  982.    if (fp)
  983.       fclose (fp);
  984.  
  985.    if (locate_y > 1 && !(fullscreen && un_attended))
  986.       gotoxy (2, locate_y - 1);
  987.    throughput (1, dh->size);    /*PLF Fri  05-05-1989  23:18:08 */
  988.  
  989.    if (real_errs > 4)
  990.       status_line ("+Corrected %d errors in %ld blocks", real_errs, last_block);
  991.    status_line ("+Sent-S %s", fname);
  992.  
  993.    update_files (1);
  994.    closedir(dh); dh=NULL;    /*PLF Fri  05-05-1989  23:18:25 */
  995.    return ackerr;
  996. }
  997.  
  998. /* END OF FILE: F_Send.C */
  999.