home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / BTMTSRC3.ZIP / XMSEND.C < prev    next >
Text File  |  1992-03-16  |  21KB  |  889 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. /*                  This module was written by Bob Hartman                  */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*                 BinkleyTerm Xmodem Sender State Machine                  */
  17. /*                                                                          */
  18. /*                                                                          */
  19. /*    For complete  details  of the licensing restrictions, please refer    */
  20. /*    to the License  agreement,  which  is published in its entirety in    */
  21. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.240.    */
  22. /*                                                                          */
  23. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  24. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  25. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  26. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  27. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  28. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  29. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  30. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  31. /*                                                                          */
  32. /*                                                                          */
  33. /* You can contact Bit Bucket Software Co. at any one of the following      */
  34. /* addresses:                                                               */
  35. /*                                                                          */
  36. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:132/491, 1:141/491  */
  37. /* P.O. Box 460398                AlterNet 7:491/0                          */
  38. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  39. /*                                Internet f491.n132.z1.fidonet.org         */
  40. /*                                                                          */
  41. /* Please feel free to contact us at any time to share your comments about  */
  42. /* our software and/or licensing policies.                                  */
  43. /*                                                                          */
  44. /*--------------------------------------------------------------------------*/
  45.  
  46.  
  47. #define INCL_DOSPROCESS
  48.  
  49.  
  50. /* System include files */
  51. #include <fcntl.h>
  52. #include <stdio.h>
  53. #include <sys/types.h>
  54. #include <sys/stat.h>
  55. #include <io.h>
  56. #include <stdlib.h>
  57. #include <conio.h>
  58. #include <string.h>
  59. #include <os2.h>            /* CML */
  60.  
  61. #ifdef __TURBOC__
  62. #include <mem.h>
  63. #else
  64. #include <memory.h>
  65. #endif
  66.  
  67. /* Local include files */
  68. #include "defines.h"
  69. #include "com.h"
  70. #include "xfer.h"
  71. #include "zmodem.h"
  72. #include "keybd.h"
  73. #include "sbuf.h"
  74. #include "sched.h"
  75. #include "externs.h"
  76. #include "prototyp.h"
  77.  
  78.  
  79. static first_block = 0;                /* CML */
  80.  
  81.  
  82.  
  83. void Build_Header_Block (args, type)
  84. XMARGSP args;
  85. char type;
  86. {
  87.    struct FILEINFO dta;
  88.     SEADATAP ttmp;
  89.  
  90.    (void) dfind (&dta, args->filename, 0);
  91.     args->save_header = type;
  92.     ttmp = (SEADATAP) &(args->header);
  93.  
  94.     (void) memset (ttmp, 0, sizeof (XMDATA));
  95.     ttmp->header = type;
  96.     ttmp->block_num = 0;
  97.     ttmp->block_num_comp = 0xff;
  98.     ttmp->filelength = args->filelen;
  99.    (void) strcpy (ttmp->sendingprog, xfer_id);
  100.     if (type == SYN)
  101.         {
  102.        (void) memset (ttmp->filename, ' ', 16);
  103.         ttmp->timedate = dta.time;
  104.         /* This is the CRC bit in the TeLink header */
  105.         ttmp->Resync = 1;
  106.         }
  107.     else
  108.         {
  109.         ttmp->timedate = args->save_filetime.oneword.timedate;
  110.         ttmp->SLO = (unsigned char) (((cur_baud >= 9600) && !no_overdrive)? 1 : 0);
  111.         ttmp->Resync = (unsigned char) (no_resync ? 0 : 1);
  112.         ttmp->MACFLOW = 1;
  113.         }
  114.     if (args->temp_name != NULL)
  115.         (void) strncpy (ttmp->filename, args->temp_name, strlen (args->temp_name));
  116.     else
  117.         (void) strncpy (ttmp->filename, (char *) (dta.name), strlen (dta.name));
  118.     first_block = 1;            /* CML */
  119. }
  120.  
  121. void XSSetVars (XMARGSP);
  122. int XSInit (XMARGSP, int);
  123. int XSEnd (XMARGSP, int);
  124. int XSXmtStart (XMARGSP);
  125. int XSXmTeStrt (XMARGSP);
  126. int XSCheckACK (XMARGSP);
  127. int XSSendBlk (XMARGSP);
  128. int XSWaitEnd (XMARGSP);
  129.  
  130. STATES Xmodem_Sender[] = {
  131.    { "XSInit", XSInit },
  132.    { "XSEnd",  XSEnd },
  133.    { "XS0",    XSXmtStart },
  134.    { "XS0T",   XSXmTeStrt },
  135.    { "XS1",    XSCheckACK },
  136.    { "XS2",    XSSendBlk },
  137.    { "XS3",    XSWaitEnd }
  138. };
  139.  
  140. int XSInit (args, start_state)
  141. XMARGSP args;
  142. int start_state;
  143. {
  144.     struct stat st;
  145.     char junkbuff[100];
  146.  
  147.     /* Get the file information */
  148.     if (stat (args->filename, &st))
  149.         {
  150. /* Print error message */
  151.         return (OPEN_ERR);
  152.         }
  153.  
  154.     if ((args->file_pointer = fopen (args->filename, "rb")) == NULL)
  155.         {
  156. /* Print error message */
  157.         return (OPEN_ERR);
  158.         }
  159.  
  160.     /* Get important information out of it */
  161.     args->filelen = st.st_size;
  162.     args->LastBlk = (st.st_size + 127) / 128;
  163.     args->save_filetime.oneword.timedate = st.st_atime;
  164.     args->prev_bytes = 0L;
  165.     args->tot_errs = 0;
  166.  
  167.    (void) sprintf (junkbuff, msgtxt[M_SEND_MSG], args->LastBlk, args->filename, st.st_size);
  168.    if (un_attended && fullscreen)
  169.       {
  170.       clear_filetransfer ();
  171.       sb_move (filewin, 1, 2);
  172.       sb_puts (filewin, (unsigned char *) junkbuff);
  173.       elapse_time ();
  174.       sb_show ();
  175.       }
  176.    else
  177.       {
  178.       status_line ("+%s", junkbuff);
  179.       printf ("\n");
  180.       }
  181.  
  182.    locate_y = wherey ();
  183.    locate_x = wherex ();
  184.  
  185.     /* Start the throughput calculations */
  186.     throughput (0, 0L);
  187.  
  188.    return (start_state);
  189. }
  190.  
  191. int XSEnd (args, cur_state)
  192. XMARGSP args;
  193. int cur_state;
  194. {
  195.    args->result = cur_state;
  196.  
  197.     /* Close file */
  198.     fclose (args->file_pointer);
  199.  
  200.    if (args->tot_errs > 3)
  201.       status_line (msgtxt[M_CORRECTED_ERRORS], args->tot_errs, args->LastBlk);
  202.  
  203.     /* Log that we sent it */
  204.    if (cur_state == SUCCESS)
  205.       {
  206.       throughput (1, (unsigned long) (args->filelen - args->prev_bytes));
  207.       status_line ("%s: %s", msgtxt[M_FILE_SENT], args->filename);
  208.       update_files (1);
  209.       }
  210.  
  211.    return (cur_state);
  212. }
  213.  
  214. void XSSetVars (args)
  215. XMARGSP args;
  216. {
  217.    if (no_sealink)
  218.       {
  219.       args->options.SLO = 0;
  220.       args->options.Resync = 0;
  221.       }
  222.    else
  223.       {
  224.       args->options.SLO = ((cur_baud >= 9600) && !no_overdrive) ? 1 : 0;
  225.       args->options.Resync = (~no_resync) & 1;
  226.       }
  227.  
  228.     args->options.SEAlink = 0;
  229.     args->SendBLK = 1;
  230.    args->curr_byte = 0L;
  231.     args->NextBLK = 1;
  232.     args->ACKST = 0;
  233.     args->ACKBLK = -1L;
  234.     args->Window = 1;
  235.     args->ACKsRcvd = 0;
  236.     args->NumNAK = 0;
  237.     args->T1 = timerset (3000);
  238. }
  239.  
  240. int XSXmtStart (args)
  241. XMARGSP args;
  242. {
  243.     XSSetVars (args);
  244.     Build_Header_Block (args, SOH);
  245.     return (XS1);
  246. }
  247.  
  248. int XSXmTeStrt (args)
  249. XMARGSP args;
  250. {
  251.     XSSetVars (args);
  252.     Build_Header_Block (args, SYN);
  253.     return (XS1);
  254. }
  255.  
  256. int XSCheckACK (args)
  257. XMARGSP args;
  258. {
  259.     Check_ACKNAK (args);
  260.     return (XS2);
  261. }
  262.  
  263. int XSSendBlk (args)
  264. XMARGSP args;
  265. {
  266.     if (!CARRIER)
  267.         return (CARRIER_ERR);
  268.  
  269.    if (got_ESC ())
  270.       {
  271.       status_line (msgtxt[M_KBD_MSG]);
  272.         return (KBD_ERR);
  273.       }
  274.  
  275.     if ((args->NumNAK > 4) && (args->SendBLK == 0))
  276.         {
  277.         if (args->save_header == SOH)
  278.             return (XS0T);
  279.         else
  280.             {
  281.             args->NumNAK = 0;
  282.             ++(args->ACKBLK);
  283.             ++(args->SendBLK);
  284.             return (XS2);
  285.             }
  286.         }
  287.  
  288.     if (args->NumNAK > 10)
  289.         {
  290. /* Too Many Errors */
  291.         return (SEND_RETRY_ERR);
  292.         }
  293.  
  294.     if (timeup (args->T1))
  295.         {
  296. /* Fatal Timeout */
  297.         return (SEND_TIMEOUT);
  298.         }
  299.  
  300.     if (args->SendBLK > (args->LastBlk + 1))
  301.         return (XS3);
  302.  
  303.     if (args->SendBLK > (args->ACKBLK + args->Window))
  304.         {
  305.         time_release ();
  306.         return (XS1);
  307.         }
  308.  
  309.     if (args->SendBLK == (args->LastBlk + 1))
  310.         {
  311.         SENDBYTE (EOT);
  312.         ++(args->SendBLK);
  313.         args->T1 = timerset (3000);
  314.         show_sending_blocks (args);
  315.         time_release ();
  316.         return (XS1);
  317.         }
  318.  
  319.     /*
  320.         Increment the block count before sending because we read the next
  321.         block immediately after sending this block.  On error free connects
  322.         we have a big net win because we never do a seek, and while we are
  323.         sending one block, we read the next.  If we do get errors, then we
  324.         have to seek back to the previous block, and that will be a bother.
  325.         With today's phone lines and modems, we'll assume error free is more
  326.         often than not, and take our chances.
  327.     */
  328.     if (args->options.SLO && args->options.SEAlink)
  329.         {
  330.         args->ACKBLK = args->SendBLK;
  331.         }
  332.  
  333.     ++(args->SendBLK);
  334.    args->curr_byte += 128L;
  335.     Send_Block (args);
  336.     args->T1 = timerset (6000);
  337.     return (XS1);
  338. }
  339.  
  340. int XSWaitEnd (args)
  341. XMARGSP args;
  342. {
  343.     show_sending_blocks (args);
  344.  
  345.     if (args->ACKBLK < (args->LastBlk + 1))
  346.         {
  347.         time_release ();
  348.         return (XS1);
  349.         }
  350.  
  351.     if (!CARRIER)
  352.         return (CARRIER_ERR);
  353.  
  354.     return (SUCCESS);
  355. }
  356.  
  357. int SEAlink_Send_File (filename, sendname)
  358. char *filename;
  359. char *sendname;
  360. {
  361.    XMARGS xm;
  362.  
  363.     xm.filename = filename;
  364.     xm.temp_name = sendname;
  365.    return (state_machine (Xmodem_Sender, &xm, XS0));
  366. }
  367.  
  368. int Xmodem_Send_File (filename, sendname)
  369. char *filename;
  370. char *sendname;
  371. {
  372.     return (SEAlink_Send_File (filename, sendname));
  373. }
  374.  
  375. int Telink_Send_File (filename, sendname)
  376. char *filename;
  377. char *sendname;
  378. {
  379.    XMARGS xm;
  380.  
  381.     xm.filename = filename;
  382.     xm.temp_name = sendname;
  383.    return (state_machine (Xmodem_Sender, &xm, XS0T));
  384. }
  385.  
  386. void Get_Block (args)
  387. XMARGSP args;
  388. {
  389.     XMDATAP xtmp;
  390.  
  391.     if (args->SendBLK == 0)
  392.         {
  393.         Build_Header_Block (args, args->save_header);
  394.         args->NextBLK = -1L;
  395.         return;
  396.         }
  397.  
  398.     xtmp = (XMDATAP) &(args->header);
  399.  
  400.     /* Set up buffer as all ^Zs for EOF */
  401.     (void) memset (xtmp, SUB, sizeof (XMDATA));
  402.  
  403.     /* Now set up the header stuff */
  404.     xtmp->header = SOH;
  405.     xtmp->block_num = (unsigned char) (args->SendBLK & 0xff);
  406.     xtmp->block_num_comp = ~xtmp->block_num;
  407.  
  408.     if (args->NextBLK != args->SendBLK)
  409.         {
  410.        (void) fseek (args->file_pointer, (args->SendBLK - 1) * 128, SEEK_SET);
  411.         }
  412.  
  413.     args->NextBLK = args->SendBLK + 1;
  414.  
  415.     /* Can we read any data? */
  416.     if (fread ((char *) xtmp->data_bytes, 1, 128, args->file_pointer) <= 0)
  417.         return;
  418.  
  419.     /* Looks good */
  420.     return;
  421.     }
  422.  
  423. void Send_Block (args)
  424. XMARGSP args;
  425. {
  426.     if (args->header == SYN)
  427.         {
  428.        Data_Check ((XMDATAP) &(args->header), CHECKSUM);
  429.         }
  430.     else
  431.         {
  432.        Data_Check ((XMDATAP) &(args->header), args->options.do_CRC ? CRC : CHECKSUM);
  433.         }
  434.  
  435.     if ((!(args->options.do_CRC)) || (args->header == SYN))
  436.         {
  437.         SENDCHARS ((char *) &(args->header), sizeof (XMDATA) - 1, 1);
  438.         }
  439.     else
  440.         {
  441.       SENDCHARS ((char *) &(args->header), sizeof (XMDATA), 1);
  442.         }
  443.  
  444.     if (first_block)            /* CML: clean up BLOCK 0 send */
  445.         {
  446.         while (com_online && !com_out_empty())
  447.             {
  448.             if (com_char_avail())            /* CML */
  449.                 CLEAR_INBOUND();
  450. // status_line("  Clearing Inbound!");
  451.             DosSleep(1L);
  452.             }
  453.         }
  454.     UNBUFFER_BYTES ();
  455.  
  456.     show_sending_blocks (args);
  457.  
  458.     Get_Block (args);
  459. }
  460.  
  461. void show_num (args, b)
  462. XMARGSP args;
  463. long b;
  464. {
  465.     if (b > args->LastBlk)
  466.         {
  467.         if (fullscreen && un_attended)
  468.             sb_puts (filewin, "EOT");
  469.         else
  470.             cputs ("EOT");
  471.         }
  472.     else if (b >= 0L)
  473.         {
  474.         if (fullscreen && un_attended)
  475.           sb_puts (filewin, (unsigned char *) ultoa (((unsigned long) b), e_input, 10));
  476.         else
  477.           (void) cputs (ultoa (((unsigned long) b), e_input, 10));
  478.         }
  479. }
  480.  
  481. void show_sending_blocks (args)
  482. XMARGSP args;
  483. {
  484.    char j[100];
  485.    int i;
  486.    long k;
  487.  
  488.    k = args->filelen - args->curr_byte;
  489.    if (k < 0L)
  490.       k = 0L;
  491.  
  492.     if (lock_baud)            /* CML correctly calculating send/receive time */
  493.         i = (int) ((k * 10 / actual_baud * 100 / ((args->save_header == SOH) ? 94 : 70) + 59) / 60);
  494.     else 
  495.         i = (int) ((k * 10 / cur_baud * 100 / ((args->save_header == SOH) ? 94 : 70) + 59) / 60);
  496.    sprintf (j, "%3d min", i);
  497.  
  498.     if (args->options.SLO)
  499.         {
  500.         if ((!((args->SendBLK - 1) & 0x1f)) || ((args->SendBLK - 1) > args->LastBlk))
  501.             {
  502.            if (fullscreen && un_attended)
  503.               {
  504.                elapse_time();
  505.               sb_move (filewin, 2, 2);
  506.                 show_num (args, args->SendBLK - 1);
  507.                 (void) sb_putc (filewin, ':');
  508.                 show_num (args, args->ACKBLK);
  509.               (void) sb_puts (filewin, " *Overdrive*  ");
  510.             sb_move (filewin, 2, 69);
  511.             sb_puts (filewin, j);
  512.               sb_show ();
  513.               }
  514.            else
  515.               {
  516.               gotoxy (locate_x, locate_y);
  517.                 show_num (args, args->SendBLK - 1);
  518.                 cputs (":");
  519.                 show_num (args, args->ACKBLK);
  520.               (void) cputs (" *Overdrive*  ");
  521.               }
  522.             }
  523.         }
  524.     else
  525.         {
  526.        if (fullscreen && un_attended)
  527.           {
  528.            elapse_time();
  529.           sb_move (filewin, 2, 2);
  530.             show_num (args, args->SendBLK - 1);
  531.           (void) sb_putc (filewin, ':');
  532.             show_num (args, args->ACKBLK);
  533.           sb_puts (filewin, (unsigned char *) "              ");
  534.          sb_move (filewin, 2, 69);
  535.          sb_puts (filewin, j);
  536.           sb_show ();
  537.           }
  538.        else
  539.           {
  540.           gotoxy (locate_x, locate_y);
  541.             show_num (args, args->SendBLK - 1);
  542.           (void) cputs (":");
  543.             show_num (args, args->ACKBLK);
  544.           (void) cputs ("              ");
  545.           }
  546.         }
  547. }
  548.  
  549. int ACInit (XMARGSP, int);
  550. int ACEnd (XMARGSP, int);
  551. int ACChkRcvd (XMARGSP);
  552. int ACSLCheck (XMARGSP);
  553. int ACSLVerify (XMARGSP);
  554. int ACSLACKNAK (XMARGSP);
  555. int ACXMCheck (XMARGSP);
  556. int ACSLOCheck (XMARGSP);
  557. int ACSL1Check (XMARGSP);
  558. int ACACKNAK (XMARGSP);
  559. int ACXMACK (XMARGSP);
  560. int ACXMNAK (XMARGSP);
  561. int ACRESYNC (XMARGSP);
  562.  
  563. STATES ACKNAK_Check[] = {
  564.    { "ACInit", ACInit },
  565.    { "ACEnd",  ACEnd },
  566.    { "AC0",    ACChkRcvd },
  567.    { "AC1",    ACSLCheck },
  568.    { "AC2",    ACSLVerify },
  569.    { "AC3",    ACSLACKNAK },
  570.    { "AC4",    ACXMCheck },
  571.    { "AC5",    ACSLOCheck },
  572.    { "AC6",    ACSL1Check },
  573.    { "AC7",    ACACKNAK },
  574.    { "AC8",    ACXMACK },
  575.    { "AC9",    ACXMNAK },
  576.    { "AC10",   ACRESYNC }
  577. };
  578.  
  579. int ACInit (args, start_state)
  580. XMARGSP args;
  581. int start_state;
  582. {
  583.     args->result = 0;
  584.    return (start_state);
  585. }
  586.  
  587. int ACEnd (args, cur_state)
  588. XMARGSP args;
  589. int cur_state;
  590. {
  591.    args->result = cur_state;
  592.    return (cur_state);
  593. }
  594.  
  595. int ACChkRcvd (args)
  596. XMARGSP args;
  597. {
  598.    if (PEEKBYTE () >= 0)
  599.       {
  600.       args->CHR = TIMED_READ (0);
  601.         return (AC1);
  602.       }
  603.  
  604.     return (SUCCESS);
  605. }
  606.  
  607. int ACSLCheck (args)
  608. XMARGSP args;
  609. {
  610.     if (args->ACKST > 2)
  611.         return (AC2);
  612.  
  613.     return (AC6);
  614. }
  615.  
  616. int ACSLVerify (args)
  617. XMARGSP args;
  618. {
  619.    if (args->ARBLK8 == (unsigned char) ((~args->CHR) & 0xff))
  620.       {
  621.         args->ARBLK = args->SendBLK - ((args->SendBLK - args->ARBLK8) & 0xff);
  622.         return (AC3);
  623.       }
  624.  
  625.     args->options.SEAlink = 0;
  626.     args->Window = 1;
  627.     args->ACKST = 0;
  628.     return (AC6);
  629. }
  630.  
  631. int ACSLACKNAK (args)
  632. XMARGSP args;
  633. {
  634.    if ((args->ARBLK < 0) ||
  635.        (args->ARBLK > args->SendBLK) ||
  636.        (args->ARBLK <= (args->SendBLK - 128)))
  637.       {
  638.         return (AC0);
  639.       }
  640.  
  641.    if (args->ACKST == 3)
  642.       {
  643.         args->options.SEAlink = (~no_sealink) & 1;
  644.         args->Window = calc_window ();
  645.         args->ACKBLK = args->ARBLK;
  646.         ++(args->ACKsRcvd);
  647.         args->ACKST = 0;
  648.         return (AC5);
  649.       }
  650.  
  651.     args->SendBLK = args->ARBLK;
  652.    args->curr_byte = (args->SendBLK - 1) * 128L;
  653.    if (args->curr_byte < 0L)
  654.       args->curr_byte = 0L;
  655.  
  656.     if (args->SendBLK > 0)
  657.         ++(args->tot_errs);
  658.  
  659.     Get_Block (args);
  660.     args->ACKST = 0;
  661.  
  662. /* This stuff was in 2.38 why?
  663.    CLEAR_OUTBOUND ();
  664.    if (*SLO)
  665.       *sealink = 0;
  666. */
  667.     return (AC4);
  668. }
  669.  
  670. int ACXMCheck (args)
  671. XMARGSP args;
  672. {
  673.    if (args->NumNAK < 4)
  674.       {
  675.         args->options.SEAlink = (~no_sealink) & 1;
  676.         args->Window = calc_window ();
  677.         }
  678.     else
  679.         {
  680.        args->options.SEAlink = 0;
  681.         args->Window = 1;
  682.         }
  683.     return (SUCCESS);
  684. }
  685.  
  686. int ACSLOCheck (args)
  687. XMARGSP args;
  688. {
  689.     if ((args->options.SLO == 0) || (args->ACKsRcvd < 10))
  690.         return (SUCCESS);
  691.  
  692.     args->options.SLO = 0;
  693.     return (SUCCESS);
  694. }
  695.  
  696. int ACSL1Check (args)
  697. XMARGSP args;
  698. {
  699.     if ((args->ACKST == 1) || (args->ACKST == 2))
  700.         {
  701.         args->ARBLK8 = (unsigned char) args->CHR;
  702.         args->ACKST += 2;
  703.         return (AC6);
  704.         }
  705.  
  706.     if ((args->options.SEAlink == 0) || (args->ACKST == 0))
  707.         return (AC7);
  708.  
  709.     return (AC0);
  710. }
  711.  
  712. int ACACKNAK (args)
  713. XMARGSP args;
  714. {
  715.     long mac_timer;
  716.  
  717.     switch (args->CHR)
  718.         {
  719.         case ACK:
  720.             args->ACKST = 1;
  721.             args->NumNAK = 0;
  722.             return (AC8);
  723.  
  724.         case WANTCRC:
  725.             args->options.do_CRC = 1;
  726.             /* Fallthrough */
  727.  
  728.         case NAK:
  729.          args->ACKST = 2;
  730.             ++(args->NumNAK);
  731.             CLEAR_OUTBOUND ();
  732.             timer (6);
  733.             return (AC9);
  734.  
  735.         case SYN:
  736.             CLEAR_OUTBOUND ();
  737.          if (!no_resync)
  738.             {
  739.                args->result = Receive_Resync (&(args->resync_block));
  740.                args->ACKST = 0;
  741.                return (AC10);
  742.             }
  743.          else
  744.             {
  745.             return (AC0);
  746.             }
  747.  
  748.         case DC3: /* ^S */
  749.             if (args->options.SEAlink && (args->ACKST == 0))
  750.                 {
  751.                 mac_timer = timerset (1000);
  752.                 while (CARRIER && !timeup (mac_timer))
  753.                     {
  754.                     if (TIMED_READ (0) == DC1)
  755.                         break;
  756.  
  757.                     time_release ();
  758.                     }
  759.                 return (AC0);
  760.                 }
  761.  
  762.             /* Otherwise, fallthrough */
  763.  
  764.         default:
  765.             return (AC0);
  766.         }
  767. }
  768.  
  769. int ACXMACK (args)
  770. XMARGSP args;
  771. {
  772.     if (!args->options.SEAlink)
  773.         ++(args->ACKBLK);
  774.  
  775.     return (AC0);
  776. }
  777.  
  778. int ACXMNAK (args)
  779. XMARGSP args;
  780. {
  781.     if (!args->options.SEAlink)
  782.         {
  783.         args->SendBLK = args->ACKBLK + 1;
  784.       args->curr_byte = (args->SendBLK - 1) * 128L;
  785.       if (args->curr_byte < 0L)
  786.          args->curr_byte = 0L;
  787.  
  788.         if (args->SendBLK > 0)
  789.             ++(args->tot_errs);
  790.  
  791.         Get_Block (args);
  792.         }
  793.  
  794.     return (AC0);
  795. }
  796.  
  797. int ACRESYNC (args)
  798. XMARGSP args;
  799. {
  800.    CLEAR_OUTBOUND ();
  801.     if (args->result != SUCCESS)
  802.         {
  803.         SENDBYTE (NAK);
  804.         return (SUCCESS);
  805.         }
  806.  
  807.     if (args->SendBLK == 1)
  808.         {
  809.         args->prev_bytes = (args->resync_block - 1) * 128;
  810.         if (args->prev_bytes > args->filelen)
  811.             args->prev_bytes = args->filelen;
  812.       status_line (msgtxt[M_SYNCHRONIZING], args->prev_bytes);
  813.         }
  814.     else
  815.         {
  816.         ++(args->tot_errs);
  817.         }
  818.  
  819.     args->options.SEAlink = 1;
  820.     args->Window = calc_window ();
  821.     args->SendBLK = args->resync_block;
  822.    args->curr_byte = (args->SendBLK - 1) * 128L;
  823.    if (args->curr_byte < 0L)
  824.       args->curr_byte = 0L;
  825.  
  826.     Get_Block (args);
  827.     args->ACKBLK = args->SendBLK - 1;
  828.     SENDBYTE (ACK);
  829.     return (SUCCESS);
  830. }
  831.  
  832.  
  833. void Check_ACKNAK (args)
  834. XMARGSP args;
  835. {
  836.     state_machine (ACKNAK_Check, args, AC0);
  837. }
  838.  
  839. int Receive_Resync (resync_block)
  840. long *resync_block;
  841. {
  842.    unsigned char resyncit[30];
  843.    unsigned char *p;
  844.    unsigned char a, b;
  845.    unsigned int nak_crc, his_crc;
  846.  
  847.    p = resyncit;
  848.  
  849.    while ((*p = (unsigned char) TIMED_READ(1)) != ETX)
  850.       {
  851.       if ((*p < '0') || (*p > '9'))
  852.          {
  853.          status_line (">SEAlink Send: Resync bad byte '%02x'", *p);
  854.          return (RESYNC_ERR);
  855.          }
  856.       ++p;
  857.       }
  858.    *p = '\0';
  859.    nak_crc = crc_block ((unsigned char *) resyncit, (int) strlen ((char *) resyncit));
  860.    a = (unsigned char) TIMED_READ (1);
  861.    b = (unsigned char) TIMED_READ (1);
  862.    his_crc = (b << 8) | a;
  863.  
  864.    if (nak_crc != his_crc)
  865.       {
  866.       status_line (">SEAlink Send: Resync bad crc %04x/%04x", nak_crc, his_crc);
  867.       return (CRC_ERR);
  868.       }
  869.  
  870.    *resync_block = atol ((char *) resyncit);
  871.  
  872.    status_line (">SEAlink Send: Resync to %ld", *resync_block);
  873.    return (SUCCESS);
  874. }
  875.  
  876. int calc_window ()
  877. {
  878.    int window;
  879.  
  880.    window = (int) (cur_baud / 400);
  881.    if (window <= 0)
  882.       window = 2;
  883.    if (small_window)
  884.       window = (window > 6) ? 6 : window;
  885.  
  886.    return (window);
  887. }
  888. 
  889.