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