home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 066.lha / Zterm / xmodem.c < prev    next >
Text File  |  1986-11-20  |  17KB  |  605 lines

  1. /* Create xrb - xmodem_request_block */
  2.  
  3. /* Xmodem, and associated routines for z-term */
  4. /* Nik Conwell   4/20/87 */
  5.  
  6. #include "term.h"                /* Defines */
  7. #include "term.common"
  8.  
  9. /* Send a character to the serial port */
  10.  
  11. void sendchar(ch,zt)
  12. char ch;
  13. struct Z_Term *zt;
  14. {
  15.   zt->rs_out = ch;
  16.   DoIO(zt->write_request);
  17. }
  18.  
  19.  
  20.  
  21.  
  22.  
  23. int readchar(ch,zt)
  24. char *ch;
  25. struct Z_Term *zt;
  26.  
  27. {
  28.  
  29.   set_timer(zt->timeout_time,zt);                   /* set up the timer */
  30. dowait:  zt->wakeupmask = Wait(SERIAL_INPUT |
  31.                      W1_INTUITION_MESSAGE |
  32.              TIMER_MESSAGE);
  33.   if (zt->wakeupmask & SERIAL_INPUT)
  34.    {
  35.     WaitIO(zt->read_request);
  36.     *ch = zt->rs_in;
  37.     BeginIO(zt->read_request);
  38.    }  /* end if */
  39.   if (zt->wakeupmask & W1_INTUITION_MESSAGE)
  40.     {
  41.      zt->message = (struct IntuiMessage *) GetMsg(zt->w1->UserPort);
  42.      zt->class = zt->message->Class;
  43.      zt->code = zt->message->Code;
  44.      ReplyMsg(zt->message);
  45.      if ((zt->class == MENUPICK) && (zt->code != MENUNULL))
  46.         {
  47.          zt->menunum = MENUNUM(zt->code);
  48.          zt->menuitem = ITEMNUM(zt->code);
  49.          if ((zt->menunum == MENU_FILESTUFF) && 
  50.              (zt->menuitem == MENU_FILESTUFF_ABORT_XMODEM))
  51.           {
  52.            con_put_str("\nUser Cancelled Transfer.\n",zt);
  53.            return(USER_ABORT);
  54.           }
  55.         }  /* end if the user is playing with the menu */
  56.      goto dowait;
  57.     }  /* end if we woke up because of intuition */
  58.   if (zt->wakeupmask & TIMER_MESSAGE)
  59.     {
  60.      con_put_str("\nTimeout waiting for character.\n",zt);
  61.      return(TIMEOUT);
  62.     }
  63.   return(NULL);
  64. }
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71. int xmodem_read_file(zt)
  72. struct Z_Term *zt;
  73.  
  74. {
  75.   int sectnum, errors, errorflag;
  76.   unsigned int checksum, i, j, bufptr;
  77.   unsigned char sectcurr, sectcomp, sentchecksum1, sentchecksum2;
  78.   unsigned char ourchecksum1, ourchecksum2, firstchar;
  79.   int xfer_current_blocksize, xfer_current_error_detect_alg;
  80.   int fd;
  81.   char numb[10];
  82.   char bufr[BUFSIZE];
  83.   int temp;
  84.  
  85.   firstchar = NULL;
  86.   sectcurr = NULL;
  87.   sectcomp = NULL;
  88.   sentchecksum1 = NULL;
  89.   sentchecksum2 = NULL;
  90.   xfer_current_blocksize = zt->xfer_blocksize;   /* copy blocksize */
  91.   xfer_current_error_detect_alg = zt->xfer_error_detect_alg;   /* copy spec alg  */
  92.   if ((fd = creat(zt->filename, 0)) < 0)
  93.    {
  94.     con_put_str("\nCannot Open ",zt);
  95.     con_put_str(zt->filename,zt);
  96.     con_put_str(" .  File exists.\n",zt);
  97.     goto xmodem_read_file_exit;
  98.    }
  99.   else
  100.    {
  101.     con_put_str("\nReceiving ",zt);
  102.     con_put_str(zt->filename,zt);
  103.     con_put_str(" using ",zt);
  104.     if (zt->xfer_blocksize == XMODEM_128_BLOCK)
  105.      {
  106.       con_put_str("128",zt);
  107.      }
  108.     if (zt->xfer_blocksize == XMODEM_1024_BLOCK)
  109.      {
  110.       con_put_str("1024",zt);
  111.      }
  112.     con_put_str(" byte blocks, with ",zt);
  113.     if (zt->xfer_error_detect_alg == XMODEM_CHECKSUM)
  114.      {
  115.       con_put_str("checksum",zt);
  116.      }
  117.     if (zt->xfer_error_detect_alg == XMODEM_CRC16)
  118.      {
  119.       con_put_str("crc-16",zt);
  120.      }
  121.     con_put_str(" error detection algorithm.\n",zt);
  122.    }
  123.   zt->timeout_time = 3;
  124.   sectnum = errors = bufptr = 0;
  125.   do            /* Loop until SOH or STX is received */
  126.    {
  127.     if (xfer_current_error_detect_alg == XMODEM_CHECKSUM)
  128.      {
  129.       sendchar((char) NAK,zt);        /* NAK specifies checksum recv */
  130.      }
  131.     if (xfer_current_error_detect_alg == XMODEM_CRC16)
  132.      {
  133.       sendchar((char) CCHAR,zt);        /* C specifies crc16 recv */
  134.      }
  135.  
  136.    zt->st = readchar(&firstchar,zt);
  137.  
  138.    if (zt->st == USER_ABORT)
  139.      {
  140.       goto xmodem_read_file_exit;
  141.      }
  142.    if ((zt->st == TIMEOUT) && (xfer_current_error_detect_alg == XMODEM_CHECKSUM)) 
  143.      {
  144.       con_put_str("\nSender not responding to initial NAK.\n",zt);
  145.       goto xmodem_read_file_exit;            /* if checksum, getout */
  146.      }
  147.    if ((zt->st == TIMEOUT) && (xfer_current_error_detect_alg == XMODEM_CRC16))
  148.      {
  149.       xfer_current_error_detect_alg = XMODEM_CHECKSUM;
  150.       con_put_str("\nSender not responding to CRC option.\n",zt);
  151.       con_put_str("\nXferring using checksum algorithm.\n",zt);
  152.      }
  153.    if ((firstchar != SOH) && (firstchar != STX))  /* if !SOH, tell what it is */
  154.      {
  155.       con_put_str("\nSender not sending SOH or STX.\n",zt);
  156.       temp = (int) firstchar;
  157.       stci_d(numb,temp,10);
  158.       con_put_str(numb,zt);
  159.       con_put_str(" ascii received instead.\n",zt);
  160.      }
  161.    }
  162.   while ((firstchar != SOH) && (firstchar != STX));
  163.   zt->timeout_time = 10;            /* 10 second timeout period */
  164.   while ((firstchar != EOT) && (errors < ERRORMAX))
  165.    {
  166.     errorflag = FALSE;
  167.     if ((firstchar == SOH) || (firstchar == STX))
  168.      {
  169.       if ((firstchar == SOH) && (xfer_current_blocksize == XMODEM_1024_BLOCK))
  170.        {
  171.         xfer_current_blocksize = XMODEM_128_BLOCK;
  172.     con_put_str("\nSender specified 128 byte block.\n",zt);
  173.     con_put_str("Temporarily switched block size.\n",zt);
  174.        }
  175.       if ((firstchar == STX) && (xfer_current_blocksize == XMODEM_128_BLOCK))
  176.        {
  177.         xfer_current_blocksize = XMODEM_1024_BLOCK;
  178.     con_put_str("\nSender specified 1024 byte block.\n",zt);
  179.     con_put_str("Temporarily switched block size.\n",zt);
  180.        }
  181.       con_put_str("Receiving Block ",zt);
  182.       stci_d(numb,sectnum,10);
  183.       con_put_str(numb,zt);
  184.       con_put_str("...",zt);
  185.  
  186.       zt->st = readchar(§curr,zt);
  187.       if (zt->st == USER_ABORT)
  188.         {
  189.      goto xmodem_read_file_exit;
  190.     }
  191.       if (zt->st == TIMEOUT)
  192.        {
  193.     con_put_str("\nTimeout occured while waiting for sectcurr.\n",zt);
  194.     goto xmodem_read_file_exit;
  195.        }
  196.  
  197.       zt->st = readchar(§comp,zt);
  198.       if (zt->st == USER_ABORT)
  199.         {
  200.      goto xmodem_read_file_exit;
  201.     }
  202.       if (zt->st == TIMEOUT)
  203.        {
  204.     con_put_str("\nTimeout occured while waiting for sector complement.\n",zt);
  205.     goto xmodem_read_file_exit;
  206.        }
  207.       if ((sectcurr + sectcomp) == 255)        /* must be compliment */
  208.        {
  209.         if (sectcurr == (sectnum + 1 & 0xff))    /* must be same sector */
  210.          {
  211.           checksum = 0;
  212.           for (j = bufptr; j < (bufptr + xfer_current_blocksize); j++)
  213.            {
  214.             zt->st = readchar((char *) &bufr[j],zt);
  215.             if (zt->st == USER_ABORT)
  216.               {
  217.                goto xmodem_read_file_exit;
  218.              }
  219.             if (zt->st == TIMEOUT)
  220.           {
  221.            con_put_str("\nTimeout occurred waiting for data in block.\n",zt);
  222.            goto xmodem_read_file_exit;
  223.           }
  224.             if (xfer_current_error_detect_alg == XMODEM_CHECKSUM)  /* calc checksum */
  225.           {
  226.            checksum = (checksum + bufr[j]) & 0xff;
  227.           }
  228.         if (xfer_current_error_detect_alg == XMODEM_CRC16)
  229.           {
  230.            checksum = checksum ^ (int) bufr[j] << 8;    /* calc crc16 */
  231.            for (i = 0;i < 8; ++i)
  232.             {
  233.          if (checksum & 0x8000)
  234.           {
  235.            checksum = checksum << 1 ^ 0x1021;
  236.           }
  237.          else
  238.           {
  239.            checksum = checksum << 1;
  240.           }
  241.         }  /* end for */
  242.            checksum = checksum & 0xffff;
  243.           }  /* end if error detect alg == XMODEM_CRC16 */
  244.            }  /* end for */
  245.       if (zt->xfer_error_detect_alg == XMODEM_CHECKSUM)
  246.        {
  247.         zt->st = readchar(&sentchecksum1,zt);
  248.             if (zt->st == USER_ABORT)
  249.               {
  250.            goto xmodem_read_file_exit;
  251.           }
  252.         ourchecksum1 = checksum;
  253.        }
  254.       if (xfer_current_error_detect_alg == XMODEM_CRC16)
  255.        {
  256.         zt->st = readchar(&sentchecksum1,zt);
  257.             if (zt->st == USER_ABORT)
  258.               {
  259.            goto xmodem_read_file_exit;
  260.           }
  261.  
  262.         zt->st = readchar(&sentchecksum2,zt);
  263.             if (zt->st == USER_ABORT)
  264.               {
  265.            goto xmodem_read_file_exit;
  266.           }
  267.         ourchecksum1 = checksum >> 8;
  268.         ourchecksum2 = checksum;
  269.        }
  270.           if (((xfer_current_error_detect_alg == XMODEM_CHECKSUM) &&
  271.           (ourchecksum1 == sentchecksum1)) ||
  272.           ((xfer_current_error_detect_alg == XMODEM_CRC16) &&
  273.            (ourchecksum1 == sentchecksum1) &&
  274.            (ourchecksum2 == sentchecksum2)))
  275.            {
  276.             errors = 0;
  277.             sectnum++;
  278.             bufptr += xfer_current_blocksize;
  279.             con_put_str("ok\n",zt);
  280.             if (bufptr == BUFSIZE)
  281.              {
  282.               bufptr = 0;
  283.               if (write(fd, bufr, BUFSIZE) == EOF)
  284.                {
  285.                 con_put_str("\nError Writing File\n",zt);
  286.                 goto xmodem_read_file_exit;
  287.                }  /* end if */
  288.              }  /* end if */
  289.             sendchar((char) ACK,zt);
  290.            }  /* end if */
  291.           else        /* checksum not what we computed!!! */
  292.            {
  293.             errorflag = TRUE;
  294.             if (zt->st == TIMEOUT) 
  295.          {
  296.           goto xmodem_read_file_exit;
  297.          }
  298.         con_put_str("\nCalculated checksum != received checksum.\n",zt);
  299.         con_put_str("\nCalculated checksum1 = ",zt);
  300.         stci_d(numb,(int) ourchecksum1,10);
  301.         con_put_str(numb,zt);
  302.         con_put_str(".  Received checksum1 = ",zt);
  303.         stci_d(numb,(int) sentchecksum1,10);
  304.         con_put_str(numb,zt);
  305.         con_put_str(".\n",zt);
  306.         if (xfer_current_error_detect_alg == XMODEM_CRC16)
  307.          {
  308.           con_put_str("\nCalculated checksum2 = ",zt);
  309.           stci_d(numb,(int) ourchecksum2,10);
  310.           con_put_str(numb,zt);
  311.           con_put_str(". Received checksum2 = ",zt);
  312.           stci_d(numb,(int) sentchecksum2,10);
  313.           con_put_str(numb,zt);
  314.           con_put_str(".\n",zt);
  315.          }  /* end if */
  316.            }  /* end else */
  317.          }  /* end if sectcurr == (sectnum + 1 & 0xff) */
  318.         else
  319.          {
  320.           if (sectcurr == (sectnum & 0xff))
  321.            {
  322.             con_put_str("\nReceived Duplicate Sector\n",zt);
  323.             sendchar((char) ACK,zt);
  324.            }  /* end if sectcurr == (sectnum & 0xff) */
  325.           else 
  326.        {            /* didn't receive expected sector number */
  327.         errorflag = TRUE;
  328.         con_put_str("\nExpecting to receive sector ",zt);
  329.         stci_d(numb,(int) sectcurr,10);
  330.         con_put_str(numb,zt);
  331.         con_put_str(".\nBut received sector ",zt);
  332.         stci_d(numb,(int) sectcurr,10);
  333.         con_put_str(numb,zt);
  334.         con_put_str(" instead.\n",zt);
  335.        }
  336.          }  /* end else */
  337.        }  /* end if sectcurr + sectcomp == 255 */
  338.        else
  339.         {
  340.          con_put_str("\nSector number, and compliment are not that.\n",zt);
  341.      con_put_str("\nSector number sent = ",zt);
  342.      stci_d(numb,(int) sectcurr,10);
  343.      con_put_str(numb,zt);
  344.      con_put_str(" ascii.\n",zt);
  345.      con_put_str("\nSector complement sent = ",zt);
  346.      stci_d(numb,(int) sectcomp,10);
  347.      con_put_str(numb,zt);
  348.      con_put_str(" ascii.\n",zt);
  349.          errorflag=TRUE;
  350.         }  /* end else */
  351.      }  /* end if firstchar == SOH || STX */
  352.     else
  353.      {
  354.       con_put_str("\nOOPS!!  We didn't receive SOH or STX!!\n",zt);
  355.      }
  356.     if (errorflag == TRUE)
  357.      {
  358.       errors++;
  359.       con_put_str("\nError\n",zt);
  360.       sendchar((char) NAK,zt);
  361.      }  /* end if errorflag == true */
  362.                 /* Read the SOH ^ STX */
  363.    zt->st = readchar(&firstchar,zt);
  364.    if (zt->st == USER_ABORT)
  365.      {
  366.       goto xmodem_read_file_exit;
  367.      }
  368.  
  369.    }  /* end while */
  370.  
  371.   write(fd,bufr,bufptr);
  372.   close(fd);
  373.  
  374.   if ((firstchar == EOT) && (errors < ERRORMAX)) 
  375.    {
  376.     sendchar((char) ACK,zt);
  377.     return(TRUE);
  378.    }
  379.   goto xmodem_read_file_exit_do;
  380. xmodem_read_file_exit:
  381.   write(fd,bufr,bufptr);
  382.   close(fd);
  383. xmodem_read_file_exit_do:
  384.   return(FALSE);
  385. }
  386.  
  387.  
  388.  
  389.  
  390.  
  391. int xmodem_send_file(zt)
  392.  
  393. struct Z_Term *zt;
  394.  
  395. {
  396.   int sectnum, bytes_to_send, size, attempts, j;
  397.   unsigned char sectsend, c;
  398.   unsigned int checksum, bufptr;
  399.   struct FileLock *lock1, *Lock();
  400.   struct FileInfoBlock *infoblock1 = 0;  
  401.   LONG filesize;
  402.   int xfer_current_error_detect_alg;
  403.   int i;
  404.   unsigned char outchecksum1;
  405.   int sync_lost_count;
  406.   int xfer_total_blocks;
  407.   int timeout_time, fd;
  408.   char bufr[BUFSIZE];
  409.   char numb[10];
  410.   int temp;
  411.  
  412.   xfer_current_error_detect_alg = NULL;     /* nullify alg */
  413.   timeout_time = 10;                /* 10 sec timeout period */
  414.   if ((lock1 = Lock(zt->filename,ACCESS_READ)) != NULL)    /* get shared lock */
  415.    {
  416.     infoblock1 = (struct FileInfoBlock *)
  417.             AllocMem(sizeof(*infoblock1),MEMF_PUBLIC|MEMF_CLEAR);
  418.     Examine(lock1,infoblock1);
  419.     filesize = infoblock1->fib_Size;
  420.     UnLock(lock1);
  421.     FreeMem(infoblock1,sizeof(*infoblock1));
  422.     con_put_str("\nSending ",zt);
  423.     con_put_str(zt->filename,zt);
  424.     con_put_str(".\n",zt);
  425.     con_put_str("File is ",zt);
  426.     stci_d(numb,(int) filesize,10);
  427.     con_put_str(numb,zt);
  428.     con_put_str(" bytes long.\n",zt);
  429.     con_put_str("Current blocksize is ",zt);
  430.     stci_d(numb,zt->xfer_blocksize,10);
  431.     con_put_str(numb,zt);
  432.     con_put_str(" bytes.\nCurrent error detection algorithm is ",zt);
  433.     if (zt->xfer_error_detect_alg == XMODEM_CHECKSUM)
  434.       {
  435.        con_put_str("checksum",zt);
  436.       }
  437.     if (zt->xfer_error_detect_alg == XMODEM_CRC16)
  438.       {
  439.        con_put_str("crc-16",zt);
  440.       }
  441.     xfer_total_blocks = (filesize / zt->xfer_blocksize);
  442.     xfer_total_blocks += 1;
  443.     con_put_str(".\nTotal blocks to send is ",zt);
  444.     stci_d(numb,xfer_total_blocks,10);
  445.     con_put_str(numb,zt);
  446.     con_put_str(".",zt);
  447.     if ((fd = open(zt->filename, 1)) == NULL)
  448.      {
  449.       con_put_str("\nError opening send file.\n",zt);
  450.       goto xmodem_send_file_exit;
  451.      }
  452.     con_put_str("\nSending File\n",zt);
  453.    }  /* end if lock1 != NULL */
  454.   else
  455.    {
  456.     con_put_str("\nCould not open ",zt);
  457.     con_put_str(zt->filename,zt);
  458.     con_put_str(" for input.\n",zt);
  459.     goto xmodem_send_file_exit;
  460.    }
  461.  
  462.   attempts = 0;
  463.   sectnum = 1;
  464.   sectsend = 1;
  465.  
  466.   /* wait for sync char */
  467.  
  468.   sync_lost_count = 1;
  469.  
  470.  
  471.  
  472.   do
  473.     {
  474.      zt->st = readchar(&c,zt);
  475.     if (zt->st == USER_ABORT)
  476.        {
  477.         goto xmodem_send_file_exit;
  478.        }
  479.  
  480.     if ((c != NAK) && (c != CCHAR))
  481.      {
  482.       con_put_str("Not receiving C or NAK.\nAscii ",zt);
  483.       temp = (int) c;
  484.       stci_d(numb,temp,10);
  485.       con_put_str(numb,zt);
  486.       con_put_str(" received instead.\n",zt);
  487.      }
  488.     }
  489.   while (((c != NAK) && (c != CCHAR)) && (sync_lost_count++ < ERRORMAX));
  490.  
  491.   if (sync_lost_count >= (ERRORMAX))
  492.    {
  493.     con_put_str("\nCouldn't sync up.\n",zt);
  494.     con_put_str("\nReceiver not sending NAKs or C's.\n",zt);
  495.     goto xmodem_send_file_exit;
  496.    }
  497.  
  498.   if (c == NAK)
  499.    {
  500.     xfer_current_error_detect_alg = XMODEM_CHECKSUM;
  501.    }
  502.   if (c == CCHAR)
  503.    {
  504.     xfer_current_error_detect_alg = XMODEM_CRC16;
  505.    }
  506.   if (xfer_current_error_detect_alg == NULL)
  507.    {
  508.     con_put_str("\nERROR!!  Receiver specified unknown error detect alg.\n",zt);
  509.     temp = (int) c;
  510.     stci_d(numb,temp,10);
  511.     con_put_str("\nAscii ",zt);
  512.     con_put_str(numb,zt);
  513.     con_put_str(" was received.\n",zt);
  514.     goto xmodem_send_file_exit;
  515.    }
  516.   if (xfer_current_error_detect_alg != zt->xfer_error_detect_alg)
  517.    {
  518.     con_put_str("\nReceiver specified error detection algorithm to be ",zt);
  519.     if (xfer_current_error_detect_alg == XMODEM_CHECKSUM)
  520.      {
  521.       con_put_str("checksum",zt);
  522.      }
  523.     if (xfer_current_error_detect_alg == XMODEM_CRC16)
  524.      {
  525.       con_put_str("crc-16",zt);
  526.      }
  527.     con_put_str(" instead of ",zt);
  528.     if (zt->xfer_error_detect_alg == XMODEM_CHECKSUM)
  529.      {
  530.       con_put_str("checksum.\n",zt);
  531.      }
  532.     if (zt->xfer_error_detect_alg == XMODEM_CRC16)
  533.      {
  534.       con_put_str("crc-16.\n",zt);
  535.      }
  536.    }  /* end if current_error_detect_alg != error_detect_alg */
  537.  
  538.   while ((bytes_to_send = read(fd, bufr, BUFSIZE)) && (attempts != RETRYMAX))
  539.    {
  540.     if (bytes_to_send == EOF)
  541.      {
  542.       con_put_str("\nError Reading File\n",zt);
  543.       goto xmodem_send_file_exit;
  544.      }
  545.  
  546.     bufptr = 0;
  547.     while ((bytes_to_send > 0) && (attempts != RETRYMAX))
  548.      {
  549.       attempts = 0;
  550.       do
  551.        {
  552.     if (zt->xfer_blocksize == XMODEM_128_BLOCK)
  553.      {
  554.       sendchar((char) SOH,zt);
  555.      }
  556.     if (zt->xfer_blocksize == XMODEM_1024_BLOCK)
  557.      {
  558.       sendchar((char) STX,zt);
  559.      }
  560.     sendchar((char) sectsend,zt);
  561.     sendchar((char) ~sectsend,zt);
  562.  
  563.         checksum = 0;
  564.         size = zt->xfer_blocksize 
  565.                <= bytes_to_send ? zt->xfer_blocksize : bytes_to_send;
  566.         bytes_to_send -= size;
  567.         for (j = bufptr; j < (bufptr + zt->xfer_blocksize); j++)
  568.          {
  569.           if (j < (bufptr + size))
  570.            {
  571.             sendchar((char) bufr[j],zt);
  572.         if (xfer_current_error_detect_alg == XMODEM_CHECKSUM)
  573.          {
  574.           checksum += bufr[j];
  575.          }
  576.         if (xfer_current_error_detect_alg == XMODEM_CRC16)
  577.          {
  578.           checksum = checksum ^ (int) bufr[j] << 8;
  579.           for (i = 0;i < 8; ++i)
  580.            {
  581.             if (checksum & 0x8000)
  582.          {
  583.           checksum = checksum << 1 ^ 0x1021;
  584.          }
  585.         else
  586.          {
  587.           checksum = checksum << 1;
  588.          }
  589.            }  /* end for */
  590.           checksum = checksum & 0xffff;
  591.          }  /* end if */
  592.            }
  593.           else 
  594.            {
  595.            sendchar((char) NULL,zt);
  596.            }
  597.          }  /* end for */
  598.     if (xfer_current_error_detect_alg == XMODEM_CHECKSUM)
  599.      {
  600.           sendchar((char) checksum & 0xff,zt);
  601.      }
  602.         if (xfer_current_error_detect_alg == XMODEM_CRC16)
  603.      {
  604.       outchecksum1 = (checksum >> 8);
  605.       sen