home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / BSRC_250.LZH / XMREC.C < prev    next >
C/C++ Source or Header  |  1991-09-15  |  37KB  |  1,249 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software, Co.                       */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          Freely Available<tm> Software.                 */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*  (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*                  This module was written by Bob Hartman                  */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*                BinkleyTerm Xmodem Receiver 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.250.    */
  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:343/491             */
  37. /* P.O. Box 460398                AlterNet 7:491/0                          */
  38. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  39. /*                                Internet f491.n343.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. /* Include this file before any other includes or defines! */
  47.  
  48. #include "includes.h"
  49.  
  50. void Find_Char (int);
  51. int Header_in_data (unsigned char *);
  52. void Send_ACK (XMARGSP);
  53. void Send_NAK (XMARGSP);
  54. long Open_Xmodem_File (XMARGSP);
  55.  
  56. int XRInit (XMARGSP, int);
  57. int XREnd (XMARGSP, int);
  58. int XRRecInit (XMARGSP);
  59. int XRBrecInit (XMARGSP);
  60. int XRRecStart (XMARGSP);
  61. int XRWaitFirst (XMARGSP);
  62. int XRWaitBlock (XMARGSP);
  63. int XRRestart (XMARGSP);
  64. int XRSetOvrdr (XMARGSP);
  65.  
  66. STATES Xmodem_Receiver[] = {
  67.    { "XRInit",  XRInit },
  68.    { "XREnd",  XREnd },
  69.    { "XR0",  XRRecInit },
  70.    { "XR0B", XRBrecInit },
  71.    { "XR1",  XRRecStart },
  72.    { "XR2",  XRWaitFirst },
  73.    { "XR3",  XRWaitBlock },
  74.    { "XR4",  XRRestart },
  75.    { "XR5",  XRSetOvrdr }
  76. };
  77.  
  78. long Open_Xmodem_File (XMARGSP args)
  79. {
  80.    char *s1, *s2;
  81.  
  82.    if (args->file_pointer == NULL)
  83.       {
  84.       args->temp_name = calloc (1, 80);
  85.  
  86.       if (args->path != NULL)
  87.          (void) strcpy (args->temp_name, args->path);
  88.  
  89.       s1 = &(args->temp_name[strlen (args->temp_name)]);
  90.       (void) strcpy (s1, "BTXXXXXX");
  91.       s2 = mktemp (args->temp_name);
  92.       if ((s2 == NULL) || ((args->file_pointer = fopen (s2, "wb")) == NULL))
  93.          {
  94.          status_line (MSG_TXT(M_TEMP_NOT_OPEN), s2);
  95.          return (-1L);
  96.          }
  97.       }
  98.  
  99.    throughput (0, 0L);
  100.    return (0L);
  101. }
  102.  
  103. long Set_Up_Restart (XMARGSP args)
  104. {
  105.    char foo[100];
  106.    char foo1[50];
  107.    struct stat st;
  108.  
  109.    args->sub_results = 0;
  110.  
  111.    /* Look for file in directory */
  112.    if (args->path != NULL)
  113.       (void) strcpy (foo, args->path);
  114.  
  115.    if ((args->received_name != NULL) &&
  116.        (strlen (args->received_name) > 0) &&
  117.         args->options.Resync)
  118.       {
  119.       (void) strcat (foo, args->received_name);
  120.  
  121.       if (stat (foo, &st) == 0)
  122.          {
  123.          if ((st.st_size == args->filelen) && (st.st_atime == (time_t)(args->save_filetime.oneword.timedate)))
  124.             {
  125.             if ((args->file_pointer = fopen (foo, "rb+")) != NULL)
  126.                {
  127.                throughput (0, 0L);
  128.                (void) fseek (args->file_pointer, 0L, SEEK_END);
  129.                args->sub_results = DID_RESYNC;
  130.                args->temp_name = calloc (1, 80);
  131.                (void) strcpy (args->temp_name, foo);
  132.                args->prev_bytes = args->filelen;
  133.                status_line (MSG_TXT(M_ALREADY_HAVE), foo);
  134.                status_line (MSG_TXT(M_SYNCHRONIZING_EOF));
  135.                return (args->total_blocks + 1L);
  136.                }
  137.             }
  138.          }
  139.  
  140.       /* Look for file in .Z file */
  141.       if (dexists (Abortlog_name))
  142.          {
  143.          (void) sprintf (Resume_info, "%ld %lo", args->filelen, args->save_filetime.oneword.timedate);
  144.          if (check_failed (Abortlog_name, args->received_name, Resume_info, foo1))
  145.             {
  146.             foo[0] = '\0';
  147.             /* Here it looks like it was a failed WaZOO session */
  148.             if (args->path != NULL)
  149.                (void) strcpy (foo, args->path);
  150.             (void) strcat (foo, foo1);
  151.  
  152.             if ((args->file_pointer = fopen (foo, "rb+")) != NULL)
  153.                {
  154.                (void) stat (foo, &st);
  155.                throughput (0, 0L);
  156.                args->temp_name = calloc(1, 80);
  157.                (void) strcpy (args->temp_name, foo);
  158.                args->prev_bytes = (st.st_size / 128L) * 128L;
  159.                (void) fseek (args->file_pointer, args->prev_bytes, SEEK_SET);
  160.                status_line (MSG_TXT(M_SYNCHRONIZING_OFFSET), args->prev_bytes);
  161.                return (args->prev_bytes / 128L + 1L);
  162.                }
  163.             }
  164.          }
  165.       }
  166.  
  167.    return (Open_Xmodem_File (args));
  168. }
  169.  
  170. void Finish_Xmodem_Receive (XMARGSP args)
  171. {
  172.    struct stat st;
  173.    char new_name[80];
  174.    struct utimbuf times;
  175.    int i, j, k;
  176.  
  177.    /* Set the file's time and date stamp */
  178.    if ((args->save_header == SOH) || (args->save_header == SYN))
  179.       {
  180.       (void) fclose (args->file_pointer);
  181.       times.modtime = times.UT_ACTIME = (time_t) args->save_filetime.oneword.timedate;
  182.       (void) utime (args->temp_name, (UTIMBUF *)×);
  183.       }
  184.    else
  185.       {
  186.       (void) strcpy (args->received_name, "");
  187.       (void) fclose (args->file_pointer);
  188.       }
  189.  
  190.    if (args->result == SUCCESS)
  191.       {
  192.       /* Get the file information */
  193.       (void) stat (args->temp_name, &st);
  194.  
  195.       throughput (1, (unsigned long) (st.st_size - args->prev_bytes));
  196.  
  197.       update_files (0);
  198.  
  199.       if (args->sub_results & DID_RESYNC)
  200.          {
  201.          status_line ("%s: %s", MSG_TXT(M_FILE_RECEIVED), args->temp_name);
  202.          }
  203.       else
  204.          {
  205.          new_name[0] = '\0';
  206.          if (args->path != NULL)
  207.             (void) strcpy (new_name, args->path);
  208.          if ((args->filename == NULL) || (strlen (args->filename) == 0))
  209.             {
  210.             if (strlen (args->received_name) > 0)
  211.                (void) strcat (new_name, args->received_name);
  212.             else
  213.                (void) strcat (new_name, "BAD_FILE.000");
  214.             }
  215.          else
  216.             {
  217.             (void) strcat (new_name, args->filename);
  218.             }
  219.  
  220.          i = (int) strlen (args->temp_name) - 1;
  221.          j = (int) strlen (new_name) - 1;
  222.  
  223.          if (args->temp_name[i] == '.')
  224.             args->temp_name[i] = '\0';
  225.          if (new_name[j] == '.')
  226.             {
  227.             new_name[j] = '\0';
  228.             --j;
  229.             }
  230.  
  231.          i = 0;
  232.          k = is_arcmail (new_name, j);
  233.          status_line ("%s: %s", MSG_TXT(M_FILE_RECEIVED), new_name);
  234.          if ((!overwrite) || k)
  235.             {
  236.             while (rename (args->temp_name, new_name))
  237.                {
  238.                if (isdigit (new_name[j]))
  239.                   new_name[j]++;
  240.                else new_name[j] = '0';
  241.                if (!isdigit (new_name[j]))
  242.                   {
  243.                   return;
  244.                   }
  245.                i = 1;
  246.                }
  247.             CLEAR_IOERR ();
  248.             }
  249.          else
  250.             {
  251.             (void) unlink (new_name);
  252.             while (rename (args->temp_name, new_name))
  253.                {
  254.                if (!i)
  255.                   {
  256.                   status_line (MSG_TXT(M_ORIGINAL_NAME_BAD), new_name);
  257.                   }
  258.                if (isdigit (new_name[j]))
  259.                   new_name[j]++;
  260.                else new_name[j] = '0';
  261.                if (!isdigit (new_name[j]))
  262.                   {
  263.                   return;
  264.                   }
  265.                i = 1;
  266.                }
  267.             CLEAR_IOERR ();
  268.             }
  269.          if (i)
  270.             {
  271.             if (locate_y && !(fullscreen && un_attended))
  272.                gotoxy (2, locate_y - 1);
  273.             status_line (MSG_TXT(M_RENAME_MSG), new_name);
  274.             }
  275.          }
  276.  
  277.     remove_abort (Abortlog_name, args->received_name);
  278.       }
  279.    else
  280.       {
  281.     if ((args->received_name != NULL) && (strlen (args->received_name) > 0) && (args->save_header != 0))
  282.       {
  283.         (void) sprintf (Resume_info, "%ld %lo", args->filelen, args->save_filetime.oneword.timedate);
  284.       add_abort (Abortlog_name, args->received_name, args->temp_name, args->path, Resume_info);
  285.       }
  286.     else
  287.       {
  288.         /* File aborted, so remove all traces of it */
  289.        if (args->temp_name != NULL)
  290.            (void) unlink (args->temp_name);
  291.       }
  292.       }
  293.  
  294.    if (args->temp_name != NULL) {
  295.       free (args->temp_name);
  296.       }
  297. }
  298.  
  299. void Get_Telink_Info (XMARGSP args)
  300. {
  301.    char *p1;
  302.    char junkbuff[100];
  303.    TLDATAP t;
  304.    unsigned int i, j;
  305.    struct tm tmstruc;
  306.    time_t curr_time;
  307.  
  308.    /* Figure out how many blocks we will get */
  309.    t = (TLDATAP) &(args->header);
  310.    args->total_blocks = (t->filelength + 127)/ 128;
  311.    t->nullbyte = '\0';
  312.    p1 = strchr (t->filename, ' ');
  313.    if (p1 != NULL)
  314.       *p1 = '\0';
  315.    (void) strcpy (args->received_name, t->filename);
  316.    args->save_header = args->header;
  317.    if (args->save_header == SYN)
  318.       {
  319.       i = t->filetime.twowords.time;
  320.       j = t->filetime.twowords.date;
  321.  
  322.       curr_time = time (NULL);
  323.       tmstruc = *localtime (&curr_time); /* Structure assignment */
  324.  
  325.       tmstruc.tm_year = (j >> 9) + 70;
  326.       tmstruc.tm_mon = (j >> 5) & 0x0f;
  327.       tmstruc.tm_mday = j & 0x1f;
  328.  
  329.       tmstruc.tm_hour = i >> 11;
  330.       tmstruc.tm_min = (i >> 5) & 0x3f;
  331.       tmstruc.tm_sec = i & 0x1f;
  332.  
  333.       args->save_filetime.oneword.timedate = mktime (&tmstruc);
  334.       }
  335.    else
  336.       {
  337.       args->save_filetime.oneword.timedate = t->filetime.oneword.timedate;
  338.       }
  339.    args->filelen = t->filelength;
  340.    (void) sprintf (junkbuff, MSG_TXT(M_RECEIVE_MSG),
  341.       args->total_blocks, t->filename, t->sendingprog, t->filelength);
  342.  
  343.    (void) strncpy (args->sending_program, t->sendingprog, 15);
  344.    if (un_attended && fullscreen)
  345.       {
  346.       clear_filetransfer ();
  347.       sb_move (file_hWnd, 1, 2);
  348.       FlLnModeSet (FILE_LN_2, 1);
  349.       sb_puts( GetDlgItem (file_hWnd, FILE_LN_1), junkbuff );
  350.       elapse_time ();
  351.       sb_show ();
  352.       }
  353.    else
  354.       {
  355.       status_line ("+%s", junkbuff);
  356.       (void) printf ("\n");
  357.       locate_y = wherey ();
  358.       locate_x = wherex ();
  359.       }
  360.    }
  361.  
  362. int Read_Block (XMARGSP args)
  363. {
  364.    unsigned char *p; /* Pointers to XMODEM data */
  365.    int i;            /* Counter */
  366.    int j;            /* Counter start */
  367.    unsigned char c;  /* character being processed */
  368.    int in_char;
  369.    char junkbuff[128];
  370.    long head_timer;
  371.  
  372.    struct _pkthdr   *packet;   /* FTS-0001 packet type */
  373.    struct _pkthdr45 *pkt0045;  /* FSC-0045 packet type */
  374.    struct _pkthdr39 *pkt0039;  /* FSC-0039 packet type */   
  375.  
  376.    unsigned int cwtest;        /* Used to verify FSC-0039 type */
  377.  
  378.    if (got_ESC ())
  379.       {
  380.       status_line (MSG_TXT(M_KBD_MSG));
  381.       return (KBD_ERR);
  382.       }
  383.  
  384.    /* Set up to point into the XMODEM data structure */
  385.    p = (unsigned char *) &(args->header);
  386.  
  387.    /* Get the first character that is waiting */
  388.    *p = (unsigned char) TIMED_READ (8);
  389.  
  390.    head_timer = timerset (6000);
  391.    j = 1;
  392.    while (!timeup (head_timer))
  393.       {
  394.       /* Now key off of the header character */
  395.       switch (*p)
  396.          {
  397.          case EOT:   /* End of file */
  398.             /* Is this a valid EOT */
  399.             if (args->total_blocks <= args->WriteBLK)
  400.                {
  401.                return (EOT_BLOCK);
  402.                }
  403.             else
  404.                {
  405.                status_line (MSG_TXT(M_UNEXPECTED_EOF), args->total_blocks);
  406.                return (BAD_BLOCK);
  407.                }
  408.  
  409.          case SYN:   /* Telink block */
  410.             /* For Telink, read all of the data except the checksum */
  411.             for (i = 1; i < sizeof (TLDATA) - 2; i++)
  412.                {
  413.                /* If we go more than 5 second, then we have a short block */
  414.                if ((in_char = TIMED_READ (5)) < 0)
  415.                   {
  416.                   return (BAD_BLOCK);
  417.                   }
  418.                *(++p) = (unsigned char) (in_char & 0xff);
  419.                }
  420.  
  421.             /* if the block number or its complement are wrong, return error */
  422.             if ((args->block_num != 0) || (args->block_num_comp != 0xff))
  423.                {
  424.                return (BAD_BLOCK);
  425.                }
  426.  
  427.             /* Now calculate the checksum - Telink block always checksum mode */
  428.             Data_Check ((XMDATAP) &(args->header), CHECKSUM);
  429.  
  430.             /* See if we can receive the checksum byte */
  431.             if ((in_char = TIMED_READ (10)) < 0)
  432.                {
  433.                Xmodem_Error (MSG_TXT(M_TIMEOUT), 0L);
  434.                return (BAD_BLOCK);
  435.                }
  436.  
  437.             /* Was it right */
  438.             c = (unsigned char) (in_char & 0xff);
  439.             if (c != args->data_check[0])
  440.                {
  441.                Xmodem_Error (MSG_TXT(M_CHECKSUM), 0L);
  442.                return (BAD_BLOCK);
  443.                }
  444.             /* Everything looks good, it must be a legal TELINK block */
  445.  
  446.             Get_Telink_Info (args);
  447.             return (TELINK_BLOCK);
  448.  
  449.          case SOH:   /* Normal data block */
  450.             args->datalen = 128;
  451.             /* Read in all of the data for an XMODEM block except the checksum */
  452.             p += (j - 1);
  453.             for (i = j; i < sizeof (XMDATA) - 2; i++)
  454.                {
  455.                /* If we go more than 5 seconds, then it is a short block */
  456.                if ((in_char = TIMED_READ (5)) < 0)
  457.                   {
  458.                   return (BAD_BLOCK);
  459.                   }
  460.                *(++p) = (unsigned char) (in_char & 0xff);
  461.                }
  462.  
  463.             /* The block number is 0 to 255 inclusive */
  464.             c = (unsigned char) (args->blocknum & 0xff);
  465.  
  466.             /* Properly calculate the CRC or checksum */
  467.             Data_Check ((XMDATAP) &(args->header), args->options.do_CRC ? CRC : CHECKSUM);
  468.  
  469.             /* Can we get the checksum byte */
  470.             if ((in_char = TIMED_READ (10)) < 0)
  471.                {
  472.                Xmodem_Error (MSG_TXT(M_TIMEOUT), args->WriteBLK);
  473.                return (BAD_BLOCK);
  474.                }
  475.  
  476.             /* Is it the right value */
  477.             c = (unsigned char) (in_char & 0xff);
  478.             if (c != args->data_check[0])
  479.                {
  480.                status_line (">Xmodem Receive: Bad %s", (args->options.do_CRC)?"CRC":"checksum");
  481.                Xmodem_Error (MSG_TXT(M_CRC_MSG), args->WriteBLK);
  482.                if (args->options.do_CRC)
  483.                   (void) TIMED_READ (5);
  484.                return (BAD_BLOCK);
  485.                }
  486.  
  487.             /* If we are in CRC mode, do the second byte */
  488.             if (args->options.do_CRC)
  489.                {
  490.                /* Can we get the character */
  491.                if ((in_char = TIMED_READ (10)) < 0)
  492.                   {
  493.                   status_line (">Xmodem Receive: Timeout waiting for CRC byte 2");
  494.                   Xmodem_Error (MSG_TXT(M_TIMEOUT), args->WriteBLK);
  495.                   return (BAD_BLOCK);
  496.                   }
  497.                /* Is it right */
  498.                c = (unsigned char) (in_char & 0xff);
  499.                if (c != args->data_check[1])
  500.                   {
  501.                   Xmodem_Error (MSG_TXT(M_CRC_MSG), args->WriteBLK);
  502.                   return (BAD_BLOCK);
  503.                   }
  504.                }
  505.  
  506.             /* Do we have a valid data block */
  507.             if (args->block_num_comp != (unsigned char)((~(args->block_num)) & 0xff))
  508.                {
  509.                if (!(args->options.SEAlink))
  510.                   {
  511.                   Xmodem_Error (MSG_TXT(M_JUNK_BLOCK), args->WriteBLK);
  512.                   return (BAD_BLOCK);
  513.                   }
  514.  
  515.                p = (unsigned char *) &(args->header);
  516.                j = Header_in_data (p);
  517.                if (j)
  518.                   {
  519.                   continue;
  520.                   }
  521.  
  522.                j = 1;
  523.                Find_Char (SOH);
  524.                *p = (unsigned char) TIMED_READ (0);
  525.                }
  526.  
  527.             if ((args->WriteBLK == 1) && (args->header == SOH) && (args->block_num == 0))
  528.                {
  529.                Get_Telink_Info (args);
  530.                return (SEALINK_BLOCK);
  531.                }
  532.  
  533.             if (first_block)
  534.                {
  535.                packet = (struct _pkthdr *) args->data;
  536.                pkt0045 = (struct _pkthdr45 *) packet;
  537.                pkt0039 = (struct _pkthdr39 *) packet;
  538.  
  539.                if (!remote_capabilities)
  540.                   {
  541.                   remote_addr.Net = packet->orig_net;
  542.                   remote_addr.Node = packet->orig_node;
  543.                   if (packet->rate == 2)
  544.                      {
  545.                      /* This is a FSC-0045 (type 2.2) packet! */
  546.                      remote_addr.Zone = packet->orig_zone;
  547.                      remote_addr.Point = (unsigned) pkt0045->orig_point;
  548.  
  549.                      strncpy (junkbuff, (char *)(pkt0045->orig_domain), 8);
  550.                      junkbuff[8] = '\0';
  551.                      remote_addr.Domain = find_domain (junkbuff);
  552.                      }
  553.                   else
  554.                      {
  555.                      remote_addr.Domain = NULL;
  556.                      cwtest = (((pkt0039->CapValid) & 0x7f00) >> 8) +
  557.                               (((pkt0039->CapValid) & 0x007f) << 8);
  558.                      if (cwtest == (unsigned int)((pkt0039->CapWord) & 0x7f7f))
  559.                         {
  560.                         /* This is a FSC-0039 packet! */
  561.                         remote_addr.Zone = pkt0039->orig_zone;
  562.                         remote_addr.Point = pkt0039->orig_point;
  563.                         }
  564.                      else
  565.                         {
  566.                         remote_addr.Zone = packet->orig_zone;
  567.                         remote_addr.Point = 0;
  568.                         }
  569.                      }
  570. /*
  571.  * Here we have extracted the Zone, Net, Node, Point and Domain from the
  572.  * packet -- regardless of type. Now see if we need to map to a fake net
  573.  * or to mung the address because it's someone else's point.
  574.  */
  575.                   if ((remote_addr.Point > 0) &&
  576.                       (pvtnet >= 0) &&
  577.                       ((remote_addr.Zone == alias[assumed].Zone) || (remote_addr.Zone == 0)) &&
  578.                        (remote_addr.Net == boss_addr.Net) &&
  579.                        (remote_addr.Node == boss_addr.Node))
  580.                      {
  581.                      remote_addr.Net = pvtnet;
  582.                      remote_addr.Node = remote_addr.Point;
  583.                      remote_addr.Point = 0;
  584.                      }
  585.                   else if ((pvtnet >= 0) && (remote_addr.Point > 0))
  586.                      {
  587.                      remote_addr.Point = 0;
  588.                      remote_addr.Node = -1;
  589.                      }
  590.                   }
  591.  
  592.                if (who_is_he)
  593.                   {
  594.                   if (!remote_addr.Zone && !remote_addr.Net && !remote_addr.Node)
  595.                      {
  596.                      LOWER_DTR ();                   /* Bad trip, cut it off */
  597.                      timer (2);                    /* Wait two secs        */
  598.                      return(CARRIER_ERR);          /* Get out of here!     */
  599.                      }
  600.  
  601.                   if (nodefind (&remote_addr, 1))
  602.                      {
  603.                      if (!remote_addr.Zone)
  604.                         remote_addr.Zone = found_zone;
  605.  
  606.                      (void) sprintf (junkbuff, "%s: %s (%s)",
  607.                               MSG_TXT(M_REMOTE_SYSTEM),
  608.                               newnodedes.SystemName,
  609.                               Full_Addr_Str (&remote_addr));
  610.                      }
  611.                   else
  612.                      {
  613.                      (void) sprintf (junkbuff, "%s: %s (%s)",
  614.                               MSG_TXT(M_REMOTE_SYSTEM),
  615.                               MSG_TXT(M_UNKNOWN_MAILER),
  616.                               Full_Addr_Str (&remote_addr));
  617.                      }
  618.  
  619.                   last_type (2, &remote_addr);
  620.                   status_line (junkbuff);
  621.                   }
  622.           if (args->sending_program[0] != '\0')
  623.             {
  624.                status_line ("%s %s", MSG_TXT(M_REMOTE_USES), args->sending_program);
  625.             }
  626.           else
  627.             {
  628.                   log_product (packet->product, 0, packet->serial);
  629.             }
  630.                who_is_he = 0;
  631.                first_block = 0;
  632.                }
  633.  
  634.             if (args->WriteBLK == args->total_blocks)
  635.                {
  636.                args->datalen = (int) (args->filelen - ((args->WriteBLK - 1) * 128));
  637.                }
  638.  
  639.             /* If we got this far, it is a valid data block */
  640.             args->recblock = args->block_num;
  641.             return (XMODEM_BLOCK);
  642.  
  643.          default:    /* Bad block */
  644.             if ((args->blocknum <= 1) || (PEEKBYTE () < 0))
  645.                return (BAD_BLOCK);
  646.  
  647.             /* Garbage header, return bad */
  648.             *p = (unsigned char) TIMED_READ (0);
  649.          }
  650.       }
  651.    return (BAD_BLOCK);
  652. }
  653.  
  654. int XRInit (XMARGSP args, int start_state)
  655. {
  656.    char *HoldName;
  657.  
  658.    args->tries = 0;
  659.    args->goodfile = 1;
  660.    XON_DISABLE ();
  661.    HoldName = HoldAreaNameMunge(&called_addr);
  662.    (void) sprintf (Abortlog_name, "%s%s.Z\0",
  663.       HoldName, Hex_Addr_Str (&remote_addr));
  664.    args->sending_program[0] = '\0';
  665.    return (start_state);
  666. }
  667.  
  668. int XREnd (XMARGSP args, int cur_state)
  669. {
  670.    args->result = cur_state;
  671.    Finish_Xmodem_Receive (args);
  672.    return (cur_state);
  673. }
  674.  
  675. int XRRecInit (XMARGSP args)
  676. {
  677.    args->options.SEAlink = 0;
  678.    args->options.SLO = 0;
  679.    args->options.Resync = 0;
  680.    args->options.MacFlow = 0;
  681.    args->options.do_CRC = 1;
  682.    args->blocknum = 0;
  683.    args->WriteBLK = 1;
  684.    args->curr_byte = 0L;
  685.    args->tries = 0;
  686.    return (XR1);
  687. }
  688.  
  689. int XRBrecInit (XMARGSP args)
  690. {
  691.    args->options.SEAlink = 0;
  692.    args->options.SLO = 0;
  693.    args->options.Resync = 0;
  694.    args->options.MacFlow = 0;
  695.    args->options.do_CRC = 1;
  696.    args->blocknum = 0;
  697.    args->WriteBLK = 1;
  698.    args->curr_byte = 0L;
  699.    args->tries = 0;
  700.    return (XR2);
  701. }
  702.  
  703. int XRRecStart (XMARGSP args)
  704. {
  705.    Send_NAK (args);
  706.    return (XR2);
  707. }
  708.  
  709. int XRWaitFirst (XMARGSP args)
  710. {
  711.    long XR2Timer;
  712.  
  713.    XR2Timer = timerset (800);
  714.    if (args->tries >= 10)
  715.       {
  716.       args->goodfile = 0;
  717.       return (TIME_ERR);
  718.       }
  719.    if (args->tries == 5)
  720.       {
  721.       args->options.do_CRC = 0;
  722.       ++(args->tries);
  723.       return (XR1);
  724.       }
  725.  
  726.    while (CARRIER)
  727.       {
  728.       switch (Read_Block (args))
  729.          {
  730.          case EOT_BLOCK:
  731.         args->WriteBLK = 0;
  732.             Send_ACK (args);
  733.             return (SUCCESS_EOT);
  734.  
  735.          case TELINK_BLOCK:
  736.             if (Open_Xmodem_File (args) == -1L)
  737.                return (OPEN_ERR);
  738.             Send_ACK (args);
  739.             args->tries = 0;
  740.             return (XR3);
  741.  
  742.          case SEALINK_BLOCK:
  743.             args->options.SEAlink = no_sealink ? 0 : 1;
  744.             if (args->options.SEAlink && !no_resync)
  745.                args->options.Resync = (((SEADATAP) (&(args->header)))->Resync) != 0;
  746.             return (XR4);
  747.  
  748.          case XMODEM_BLOCK:
  749.             if (args->recblock == 1)
  750.                {
  751.                if (Open_Xmodem_File (args) == -1L)
  752.                   return (OPEN_ERR);
  753.                (void) fwrite (args->data, sizeof (unsigned char), args->datalen, args->file_pointer);
  754.                ++(args->WriteBLK);
  755.                args->curr_byte = 128L;
  756.                ++(args->blocknum);
  757.                Send_ACK (args);
  758.                args->tries = 0;
  759.                return (XR3);
  760.                }
  761.  
  762.             /* Fallthrough on wrong block */
  763.  
  764.          case BAD_BLOCK:
  765.             ++(args->tries);
  766.             return (XR1);
  767.  
  768.          case CARRIER_ERR:
  769.          case KBD_ERR:
  770.             return (CARRIER_ERR);
  771.          }
  772.  
  773.       if (timeup (XR2Timer))
  774.          {
  775.          ++(args->tries);
  776.          return (XR1);
  777.          }
  778.       }
  779.  
  780.    return (CARRIER_ERR);
  781. }
  782.  
  783. int XRWaitBlock (XMARGSP args)
  784. {
  785.    int blocknum_copy;
  786.  
  787.    if (args->tries >= 10)
  788.       {
  789.       args->goodfile = 0;
  790.       return (TIME_ERR);
  791.       }
  792.  
  793.    while (CARRIER)
  794.       {
  795.       switch (Read_Block (args))
  796.          {
  797.          case EOT_BLOCK:
  798.             args->options.SLO = 0;
  799.             Send_ACK (args);
  800.             return (SUCCESS);
  801.  
  802.          case XMODEM_BLOCK:
  803.  
  804.             blocknum_copy = (int)args->blocknum & 0xff;
  805.  
  806.             if (args->recblock == ((blocknum_copy - 1) & 0xff))
  807.                {
  808.                --(args->blocknum);
  809.                Send_ACK (args);
  810.                return (XR3);
  811.                }
  812.  
  813.             if (args->recblock == blocknum_copy)
  814.                {
  815.                (void) fwrite (args->data, sizeof (unsigned char), args->datalen, args->file_pointer);
  816.                ++(args->WriteBLK);
  817.                args->curr_byte += 128L;
  818.                Send_ACK (args);
  819.                args->tries = 0;
  820.                return (XR3);
  821.                }
  822.  
  823.             if (args->recblock < blocknum_copy)
  824.                {
  825.                args->recblock += 256;
  826.                }
  827.  
  828.             if ((args->recblock > blocknum_copy) && (args->recblock <= ((blocknum_copy + 127) & 0xff)))
  829.                {
  830.           if (args->tries != 0)
  831.             {
  832.             /* We have sent at least one nak, now only send them
  833.               every so often to allow buffers to drain */
  834.             if ((args->recblock - blocknum_copy) % 16)
  835.               return (XR3);
  836.  
  837.             /* If it is a multiple of 16, then check that it is
  838.               higher than 32 */
  839.             if ((args->recblock - blocknum_copy) / 16 < 2)
  840.               return (XR3);
  841.             }
  842.                }
  843.  
  844.             /* fallthrough on bad block */
  845.  
  846.          case BAD_BLOCK:
  847.             Send_NAK (args);
  848.             ++(args->tries);
  849.             return (XR3);
  850.  
  851.          case CARRIER_ERR:
  852.          case KBD_ERR:
  853.             return (CARRIER_ERR);
  854.          }
  855.       }
  856.  
  857.    return (CARRIER_ERR);
  858. }
  859.  
  860. int XRRestart (XMARGSP args)
  861. {
  862.    long c;
  863.  
  864.    c = Set_Up_Restart (args);
  865.    if (c == -1L)
  866.       return (OPEN_ERR);
  867.  
  868.    if ((!c) || (!(args->options.Resync)))
  869.       {
  870.       Send_ACK (args);
  871.       args->tries = 0;
  872.       }
  873.    else
  874.       {
  875.       args->WriteBLK = c;
  876.       args->curr_byte = (c - 1) * 128L;
  877.       args->blocknum = (unsigned char) ((args->WriteBLK) & 0xff);
  878.       Send_NAK (args);
  879.       }
  880.  
  881.    return (XR5);
  882. }
  883.  
  884. int XRSetOvrdr (XMARGSP args)
  885. {
  886.    if (!no_overdrive)
  887.       args->options.SLO = (((SEADATAP) (&(args->header)))->SLO) != 0;
  888.  
  889.   if (args->options.SLO)
  890.     show_block ((long) (args->WriteBLK - 1), " *Overdrive*", args);
  891.  
  892.    return (XR3);
  893. }
  894.  
  895. int Xmodem_Receive_File (char *path, char *filename)
  896. {
  897.    XMARGS xmfile;
  898.    int res;
  899.  
  900.    locate_y = wherey ();
  901.    locate_x = wherex ();
  902.    (void) memset (&xmfile, 0, sizeof (XMARGS));
  903.    xmfile.path = path;
  904.    xmfile.filename = filename;
  905.    xmfile.total_blocks = -1L;
  906.    xmfile.sent_ACK = 0;
  907.    res = state_machine (Xmodem_Receiver, &xmfile, XR0);
  908.    return (res);
  909. }
  910.  
  911. int Batch_Xmodem_Receive_File (char *path, char *filename)
  912. {
  913.    XMARGS xmfile;
  914.    int res;
  915.  
  916.    locate_y = wherey ();
  917.    locate_x = wherex ();
  918.    (void) memset (&xmfile, 0, sizeof (XMARGS));
  919.    xmfile.path = path;
  920.    xmfile.filename = filename;
  921.    xmfile.total_blocks = -1L;
  922.    xmfile.sent_ACK = 0;
  923.    res = state_machine (Xmodem_Receiver, &xmfile, XR0B);
  924.    return (res);
  925. }
  926.  
  927. int SAInit (XMARGSP, int);
  928. int SAEnd (XMARGSP, int);
  929. int SAClearLine (XMARGSP);
  930. int SASendACK (XMARGSP);
  931. int SASEAlink (XMARGSP);
  932. int SAIncBlk (XMARGSP);
  933.  
  934. STATES ACK_States[] = {
  935.    { "SAInit",  SAInit },
  936.    { "SAEnd",  SAEnd },
  937.    { "SA0",  SAClearLine },
  938.    { "SA1",  SASendACK },
  939.    { "SA2",  SASEAlink },
  940.    { "SA3",  SAIncBlk }
  941. };
  942.  
  943. int SAInit (XMARGSP args, int start_state)
  944. {
  945.    happy_compiler = args->tries; /* Makes the compiler happy! */
  946.    return (start_state);
  947. }
  948.  
  949. int SAEnd (XMARGSP args, int cur_state)
  950. {
  951.    happy_compiler = args->tries; /* Makes the compiler happy! */
  952.    return (cur_state);
  953. }
  954.  
  955. int SAClearLine (XMARGSP args)
  956. {
  957.    long SA0Timer;
  958.  
  959.    SA0Timer = timerset (3000);
  960.    if (args->options.SLO)
  961.       return (SA3);
  962.  
  963.    if (args->options.SEAlink)
  964.       return (SA1);
  965.  
  966.    while (CARRIER && !timeup (SA0Timer))
  967.       {
  968.       if (PEEKBYTE () >= 0)
  969.          {
  970.          (void) TIMED_READ (0);
  971.          time_release ();
  972.          continue;
  973.          }
  974.  
  975.       return (SA1);
  976.       }
  977.  
  978.    return (TIME_ERR);
  979. }
  980.  
  981. int SASendACK (XMARGSP args)
  982. {
  983.    SENDBYTE (ACK);
  984.    args->sent_ACK = 1;
  985.    return (SA2);
  986. }
  987.  
  988. int SASEAlink (XMARGSP args)
  989. {
  990.    if (!(args->options.SEAlink))
  991.       return (SA3);
  992.  
  993.    SENDBYTE (args->blocknum);
  994.    SENDBYTE ((unsigned char)~(args->blocknum));
  995.    return (SA3);
  996. }
  997.  
  998. void show_block (long b, char *c, XMARGSP args)
  999. {
  1000.    char j[100];
  1001.    int i;
  1002.    long k;
  1003.  
  1004.    if (fullscreen && un_attended)
  1005.       {
  1006.       elapse_time();
  1007.  
  1008.       sb_move (file_hWnd, 2, 2);
  1009.       sb_puts( GetDlgItem (file_hWnd, FILE_LN_2 + GD_STATUS),
  1010.                ultoa (((unsigned long) b), e_input, 10));
  1011.     if (c)
  1012.         sb_puts( GetDlgItem (file_hWnd, FILE_LN_2 + GD_STATUS), c );
  1013.  
  1014.       k = args->filelen - args->curr_byte;
  1015.       if (k < 0L)
  1016.          k = 0L;
  1017.  
  1018.       i = (int) ((k * 10 / cur_baud.rate_value * 100 /
  1019.          ((args->save_header == SOH) ? 94 : 70) + 59) / 60);
  1020.       (void) sprintf (j, "%3d min", i);
  1021.  
  1022.       sb_move (file_hWnd, 2, 69);
  1023.       sb_puts( GetDlgItem (file_hWnd, FILE_LN_2 + GD_STATUS), j );
  1024.       sb_show ();
  1025.       }
  1026.    else
  1027.       {
  1028.       gotoxy (locate_x, locate_y);
  1029.       (void) printf ("%s", ultoa (((unsigned long) b), e_input, 10));
  1030.     if (c)
  1031.       (void) printf ("%s", c);
  1032.       }
  1033. }
  1034.  
  1035. int SAIncBlk (XMARGSP args)
  1036. {
  1037.    ++(args->blocknum);
  1038.    if ((args->options.SLO) &&
  1039.     (((args->WriteBLK > 0) && (!((args->WriteBLK - 1) & 0x001F)) && (args->WriteBLK < args->total_blocks)) ||
  1040.       (args->WriteBLK >= args->total_blocks)))
  1041.       {
  1042.       show_block ((long) (args->WriteBLK - 1), " *Overdrive*", args);
  1043.       }
  1044.   else if ((!(args->options.SLO)) && (args->WriteBLK > 0))
  1045.       {
  1046.       show_block ((long) (args->WriteBLK - 1), NULL, args);
  1047.       }
  1048.  
  1049.    return (SUCCESS);
  1050. }
  1051.  
  1052. void Send_ACK (XMARGSP args)
  1053. {
  1054.    (void) state_machine (ACK_States, args, SA0);
  1055. }
  1056.  
  1057. void Send_Resync_Packet (XMARGSP);
  1058.  
  1059. int SNInit (XMARGSP, int);
  1060. int SNEnd (XMARGSP, int);
  1061. int SNClearLine (XMARGSP);
  1062. int SNSendNAK (XMARGSP);
  1063. int SNSEAlink (XMARGSP);
  1064. int SNAckResync (XMARGSP);
  1065.  
  1066. STATES NAK_States[] = {
  1067.    { "SNInit",  SNInit },
  1068.    { "SNEnd",  SNEnd },
  1069.    { "SN0",  SNClearLine },
  1070.    { "SN1",  SNSendNAK },
  1071.    { "SN2",  SNSEAlink },
  1072.    { "SN3",  SNAckResync }
  1073. };
  1074.  
  1075. int SNInit (XMARGSP args, int start_state)
  1076. {
  1077.    happy_compiler = args->tries; /* Makes the compiler happy! */
  1078.    return (start_state);
  1079. }
  1080.  
  1081. int SNEnd (XMARGSP args, int cur_state)
  1082. {
  1083.    happy_compiler = args->tries; /* Makes the compiler happy! */
  1084.    return (cur_state);
  1085. }
  1086.  
  1087. int SNClearLine (XMARGSP args)
  1088. {
  1089.    long SN0Timer;
  1090.  
  1091.    SN0Timer = timerset (3000);
  1092.    if (args->options.Resync)
  1093.       {
  1094.       Send_Resync_Packet (args);
  1095.       return (SN3);
  1096.       }
  1097.  
  1098.    if (args->options.SEAlink)
  1099.       return (SN1);
  1100.  
  1101.    while (CARRIER && !timeup (SN0Timer))
  1102.       {
  1103.       if (PEEKBYTE () >= 0)
  1104.          {
  1105.          (void) TIMED_READ (0);
  1106.          time_release ();
  1107.          continue;
  1108.          }
  1109.  
  1110.       return (SN1);
  1111.       }
  1112.  
  1113.    return (TIME_ERR);
  1114. }
  1115.  
  1116. int SNSendNAK (XMARGSP args)
  1117. {
  1118.    if (args->options.do_CRC && (args->sent_ACK == 0))
  1119.       SENDBYTE (WANTCRC);
  1120.    else
  1121.       SENDBYTE (NAK);
  1122.    return (SN2);
  1123. }
  1124.  
  1125. int SNSEAlink (XMARGSP args)
  1126. {
  1127.    if (!(args->options.SEAlink))
  1128.       return (SUCCESS);
  1129.  
  1130.    SENDBYTE (args->blocknum);
  1131.    SENDBYTE ((unsigned char)~(args->blocknum));
  1132.    return (SUCCESS);
  1133. }
  1134.  
  1135. int SNAckResync (XMARGSP args)
  1136. {
  1137.    long SN3Timer;
  1138.    int c;
  1139.  
  1140.    SN3Timer = timerset (3000);
  1141.  
  1142.    while (CARRIER && !timeup (SN3Timer))
  1143.       {
  1144.       if ((unsigned int)(c = TIMED_READ (10)) == 0xffff)
  1145.          {
  1146.          Send_Resync_Packet (args);
  1147.          continue;
  1148.          }
  1149.  
  1150.       if (c == ACK)
  1151.       {
  1152.       big_pause (1);
  1153.       c = PEEKBYTE();
  1154.       if ((c == SOH) || (c == EOT))
  1155.            return (SUCCESS);
  1156.       }
  1157.       }
  1158.  
  1159.    if (!CARRIER)
  1160.       return (CARRIER_ERR);
  1161.    else
  1162.       return (TIME_ERR);
  1163. }
  1164.  
  1165. void Send_NAK (XMARGSP args)
  1166. {
  1167.    (void) state_machine (NAK_States, args, SN0);
  1168. }
  1169.  
  1170. void Send_Resync_Packet (XMARGSP args)
  1171. {
  1172.    unsigned char resyncit[30];
  1173.    unsigned int nak_crc;
  1174.  
  1175.    SENDBYTE (SYN);
  1176.    (void) sprintf ((char *) resyncit, "%ld", args->WriteBLK);
  1177.    SENDCHARS ((char *) resyncit, strlen ((char *) resyncit), 1);
  1178.    nak_crc = crc_block ((unsigned char *) resyncit, (int) strlen ((char *) resyncit));
  1179.    SENDBYTE (ETX);
  1180.    SENDBYTE ((unsigned char) (nak_crc & 0xff));
  1181.    CLEAR_INBOUND ();
  1182.    SENDBYTE ((unsigned char) (nak_crc >> 8));
  1183. }
  1184.  
  1185. void Xmodem_Error (char *s, long block_number)
  1186. {
  1187.    char j[50];
  1188.    char k[50];
  1189.  
  1190.    (void) sprintf (j, "%s %s %ld", s, MSG_TXT(M_ON_BLOCK), block_number);
  1191.    (void) sprintf (k, "%-49.49s", j);
  1192.  
  1193.    status_line (">Xmodem Error: %s", k);
  1194.    if (fullscreen && un_attended)
  1195.       {
  1196.       sb_move (file_hWnd, 2, 20);
  1197.       sb_puts( GetDlgItem (file_hWnd, FILE_LN_2 + GD_SIZE), k );
  1198.       sb_show ();
  1199.       }
  1200.    else
  1201.       {
  1202.       gotoxy (locate_x + 20, locate_y);
  1203.       (void) cputs (k);
  1204.       }
  1205. }
  1206.  
  1207. void Find_Char (int c)
  1208. {
  1209.    long t1;
  1210.    long t2;
  1211.  
  1212.    t1 = timerset (3000);
  1213.    t2 = timerset (100);
  1214.    while (!timeup (t1) && !timeup (t2))
  1215.       {
  1216.       if (!CARRIER)
  1217.          break;
  1218.  
  1219.       if (PEEKBYTE () == (c & 0xff))
  1220.          break;
  1221.       else if (PEEKBYTE () >= 0)
  1222.          {
  1223.          (void) TIMED_READ (0);
  1224.          t2 = timerset (100);
  1225.          }
  1226.       }
  1227. }
  1228.  
  1229. int Header_in_data (unsigned char *p)
  1230. {
  1231.    int i;
  1232.    int j;
  1233.    char *p1;
  1234.  
  1235.    p1 = (char *) p;
  1236.    ++p1;
  1237.    j = sizeof (XMDATA) - 2;
  1238.    for (i = 1; i < j; i++, p1++)
  1239.       {
  1240.       if (*p1 == SOH)
  1241.          {
  1242.          (void) memcpy (p, p1, (unsigned int) (j - i));
  1243.          return (j - i);
  1244.          }
  1245.       }
  1246.  
  1247.    return (0);
  1248. }
  1249.