home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d114 / vt100.lha / Vt100 / xmodem.c < prev   
C/C++ Source or Header  |  1987-11-22  |  12KB  |  468 lines

  1. /*************************************************************
  2.  * vt100 terminal emulator - XMODEM protocol support
  3.  *
  4.  *    v2.7 870825 ACS - Make multi_xfer() non-recursive; on non-ESC in
  5.  *              readchar() re-do the main window's title. 
  6.  *    v2.6 870227 DBW - bug fixes for all the stuff in v2.5
  7.  *    v2.5 870214 DBW - more additions (see readme file)
  8.  *    v2.4 861214 DBW - lots of fixes/additions (see readme file)
  9.  *    v2.3 861101 DBW - minor bug fixes
  10.  *    v2.2 861012 DBW - more of the same
  11.  *    v2.1 860915 DBW - new features (see README)
  12.  *         860901 ACS - Added Parity and Word Length and support code
  13.  *         860823 DBW - Integrated and rewrote lots of code
  14.  *         860815 Steve Drew: readchar inproved with real timeouts
  15.  *    v2.0 860809 DBW - Major rewrite
  16.  *    v1.1 860720 DBW    - Switches, 80 cols, colors, bug fixes
  17.  *    v1.0 860712 DBW    - First version released
  18.  *
  19.  *************************************************************/
  20.  
  21. #include "vt100.h"
  22.  
  23. int enablexon = TRUE;
  24.  
  25. extern struct IntuiText MyTitle;
  26.  
  27. static unsigned long parity_settings[4] = {
  28.     0x96696996,
  29.     0x69969669,
  30.     0x69969669,
  31.     0x96696996 };
  32.  
  33. /************************************************************
  34. * Send a string (using sendchar below)
  35. ************************************************************/
  36.  
  37. void sendstring(s)
  38. char *s;
  39.     {
  40.     char c;
  41.  
  42.     while ((c = *s++) != '\000') sendchar(c);
  43.     }
  44.  
  45. /**************************************************************/
  46. /* send char and read char functions for the xmodem function */
  47. /************************************************************/
  48. void sendchar(ch)
  49. int ch;
  50.     {
  51.     int doxon,i,j,k;
  52.  
  53.     doxon = enablexon;
  54.     if (doxon) No_XON();
  55.     switch (p_parity) {
  56.     case 0:    /* no parity */
  57.     rs_out[0] = ch & 0xFF;
  58.     break;
  59.  
  60.     case 1: /* mark */
  61.     rs_out[0] = (ch & 0x7F) | 0x80;
  62.     break;
  63.  
  64.     case 2: /* space */
  65.     rs_out[0] = ch & 0x7F;
  66.     break;
  67.  
  68.     case 3:    /* even */
  69.     case 4: /* odd  */
  70.     i     = (ch >> 5) & 0x3;
  71.     j     = ch & 0x1F;
  72.     k     = ((parity_settings[i] >> j) & 0x1) << 7;
  73.     if (p_parity == 3)            /* even parity */
  74.         rs_out[0] = (ch & 0x7F) | k;
  75.     else                    /* odd parity */
  76.         rs_out[0] = (ch & 0x7F) | (k ^ 0x80);
  77.     }
  78.     do {
  79.     DoIO(Write_Request);
  80.     } while(Write_Request->IOSer.io_Error != 0);
  81.     if (doxon) Do_XON();
  82.     }
  83.  
  84. /* send a break to the host */
  85. void sendbreak() {
  86.     AbortIO(Read_Request);
  87.     Wait(1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit);
  88.     WaitIO(Read_Request);
  89.     Read_Request->IOSer.io_Command = SDCMD_BREAK;
  90.     DoIO(Read_Request);
  91.     Read_Request->IOSer.io_Command = CMD_READ;
  92.     SendIO(Read_Request);
  93.     }
  94.  
  95. int readchar()
  96.     {
  97.     int rd,ch;
  98.     ULONG class, waitmask;
  99.     USHORT code;
  100.  
  101.     Timer.tr_time.tv_secs = ttime;
  102.     Timer.tr_time.tv_micro = 0;
  103.     SendIO((char *) &Timer.tr_node);
  104.  
  105.     rd = FALSE;
  106.     waitmask = ((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) |
  107.         ( 1L << mywindow->UserPort->mp_SigBit) |
  108.         ( 1L << Timer_Port->mp_SigBit));
  109.     if(reqwinup)
  110.     waitmask |= (1L << reqwindow->UserPort->mp_SigBit);
  111.     while (rd == FALSE) {
  112.     Wait(waitmask);
  113.     if (CheckIO(Read_Request)) {
  114.         WaitIO(Read_Request);
  115.         ch=rs_in[0];
  116.         rd = TRUE;
  117.         SendIO(Read_Request);
  118.     }
  119.     if(reqwinup &&
  120.       (NewMessage=(struct IntuiMessage *)GetMsg(reqwindow->UserPort))) {
  121.         class = NewMessage->Class;
  122.         ReplyMsg(NewMessage);
  123.         if(class == NEWSIZE)
  124.         ReqNewSize(reqwindow->Height, reqwindow->Width);
  125.     }
  126.     if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
  127.        class = NewMessage->Class;
  128.        code = NewMessage->Code;
  129.        ReplyMsg(NewMessage);
  130.        if ((class == RAWKEY) && (code == 69)) {
  131.          AbortIO((char *) &Timer);
  132.          Wait (1L << Timer_Port->mp_SigBit);
  133.          WaitIO((char *) &Timer.tr_node);
  134.          InfoMsg1Line("ERROR: User aborted transfer");
  135.          timeout = USERABORT;
  136.          return('\0');
  137.        }
  138.        PrintIText(mywindow->RPort, &MyTitle, 0L, 0L);
  139.        continue;
  140.     }
  141.  
  142.     if (rd == FALSE && CheckIO(&Timer)) {
  143.         InfoMsg1Line("ERROR: Timeout waiting for character");
  144.         timeout = TIMEOUT;
  145.         return('\0');
  146.     }
  147.     } /* end while */
  148.     AbortIO((char *) &Timer);
  149.     Wait (1L << Timer_Port->mp_SigBit);
  150.     WaitIO((char *) &Timer.tr_node);
  151.     timeout = GOODREAD;
  152.     return(ch & (p_parity == 0 ? 0xFF : 0x7F));
  153.     }
  154.  
  155. void No_XON() {
  156.  
  157.     /* turn off XON/XOFF processing */
  158.     enablexon = FALSE;
  159.     Write_Request->io_SerFlags |= SERF_XDISABLED;
  160.     Write_Request->IOSer.io_Command = SDCMD_SETPARAMS;
  161.     DoIO(Write_Request);
  162.     Write_Request->IOSer.io_Command = CMD_WRITE;
  163.     }
  164.  
  165. void Do_XON() {
  166.     /* turn on XON/XOFF processing */
  167.     enablexon = TRUE;
  168.     Write_Request->io_SerFlags &= ~SERF_XDISABLED;
  169.     Write_Request->IOSer.io_Command = SDCMD_SETPARAMS;
  170.     DoIO(Write_Request);
  171.     Write_Request->IOSer.io_Command = CMD_WRITE;
  172.     }
  173.  
  174. /**************************************/
  175. /* xmodem send and recieve functions */
  176. /************************************/
  177.  
  178. int XMODEM_Read_File(file)
  179. char *file;
  180.     {
  181.     int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag;
  182.     unsigned int checksum, j, bufptr;
  183.     char scrstr2[40];
  184.     bytes_xferred = 0L;
  185.     ttime = TTIME_SHORT;
  186.  
  187.     if ((fd = creat(file, 0)) < 0)
  188.     {
  189.     InfoMsg2Line("XMODEM Can't Open File:",file);
  190.     return FALSE;
  191.     }
  192.     else
  193.     InfoMsg1Line("XMODEM Receive, <esc> in VT100 window to abort");
  194.  
  195.     sectnum = errors = bufptr = 0;
  196.     sendchar(NAK);
  197.     firstchar = 0;
  198.     No_XON();
  199.     while (firstchar != EOT && errors != ERRORMAX)
  200.     {
  201.     errorflag = FALSE;
  202.  
  203.     do {                                    /* get sync char */
  204.         firstchar = readchar();
  205.         if (timeout != GOODREAD) {
  206.         if (timeout == USERABORT || errors++ == ERRORMAX)
  207.             Do_XON();
  208.             return FALSE;
  209.         }
  210.         } while (firstchar != SOH && firstchar != EOT);
  211.  
  212.     if  (firstchar == SOH)
  213.         {
  214.         sprintf(scrstr2,"Getting Block %4d...",sectnum);
  215.         InfoMsgNoScroll(scrstr2);
  216.         sectcurr = readchar();
  217.         if (timeout != GOODREAD) { Do_XON(); return FALSE; }
  218.         sectcomp = readchar();
  219.         if (timeout != GOODREAD) { Do_XON(); return FALSE; }
  220.         if ((sectcurr + sectcomp) == 255)
  221.         {
  222.         if (sectcurr == ((sectnum + 1) & 0xff))
  223.             {
  224.             checksum = 0;
  225.             for (j = bufptr; j < (bufptr + SECSIZ); j++)
  226.             {
  227.             bufr[j] = readchar();
  228.             if (timeout != GOODREAD) { Do_XON(); return FALSE; }
  229.             checksum = (checksum + bufr[j]) & 0xff;
  230.             }
  231.             if (checksum == readchar() && timeout == GOODREAD)
  232.             {
  233.             errors = 0;
  234.             sprintf(scrstr2,"Block %4d verified",sectnum);
  235.             sectnum++;
  236.             bufptr += SECSIZ;
  237.             bytes_xferred += SECSIZ;
  238.             InfoMsgNoScroll(scrstr2);
  239.             if (bufptr == BufSize)
  240.                 {
  241.                 if (write(fd, bufr, BufSize-128) == EOF)
  242.                 {
  243.                 InfoMsg1Line("XMODEM: Error Writing File");
  244.                 Do_XON();
  245.                 return FALSE;
  246.                 }
  247.                 bufptr = 128;
  248.                 for (j = 0; j < 128; j++)
  249.                 bufr[j] = bufr[(BufSize-128)+j];
  250.                 }
  251.             sendchar(ACK);
  252.             }
  253.             else
  254.             {
  255.             errorflag = TRUE;
  256.             if (timeout == USERABORT) { Do_XON(); return FALSE; }
  257.             }
  258.             }
  259.         else
  260.             {
  261.             /* got a duplicate sector */
  262.             if (sectcurr == (sectnum & 0xff))
  263.             {
  264.             /* wait until we time out for 5secs */
  265.             do {
  266.                 readchar();
  267.                 } while (timeout == GOODREAD);
  268.             if (timeout == USERABORT) {
  269.                 Do_XON();
  270.                 return FALSE;
  271.                 }
  272.             InfoMsg1Line("XMODEM: Received Duplicate Sector");
  273.             sendchar(ACK);
  274.             }
  275.             else errorflag = TRUE;
  276.             }
  277.         }
  278.         else errorflag = TRUE;
  279.         }
  280.     if (errorflag == TRUE)
  281.         {
  282.         errors++;
  283.         InfoMsg1Line("XMODEM: Error");
  284.         sendchar(NAK);
  285.         }
  286.     }        /* end while */
  287.     if ((firstchar == EOT) && (errors < ERRORMAX))
  288.     {
  289.     sendchar(ACK);
  290. #ifdef BUGFIXES
  291.     /* use firstchar to remember the last char for chopping */
  292.     if (bufptr && ((firstchar = bufr[--bufptr]) == 0 || firstchar == 0x1A))
  293.         {
  294.         while (bufptr && bufr[--bufptr] == firstchar)
  295.         ;
  296.         if (bufptr || bufr[0] != firstchar)     /* check for null buffer */
  297.         write(fd, bufr, ++bufptr);
  298.         }
  299. #else
  300.     while (bufptr > 0 && (bufr[--bufptr] == 0x00 ||
  301.                   bufr[bufptr]   == 0x1A)) ;
  302.     write(fd, bufr, ++bufptr);
  303. #endif
  304.     close(fd);
  305.     Do_XON();
  306.     ScrollInfoMsg(1);
  307.     return TRUE;
  308.     }
  309.     Do_XON();
  310.     return FALSE;
  311.     }
  312.  
  313. int XMODEM_Send_File(file)
  314. char *file;
  315.     {
  316.     int sectnum, bytes_to_send, size, attempts, c;
  317.     unsigned checksum, j, bufptr;
  318.     char scrstr2[40];
  319.     bytes_xferred = 0;
  320.     ttime = TTIME_LONG;
  321.  
  322.     if ((fd = open(file, 0)) < 0) {
  323.     InfoMsg1Line("XMODEM: Cannot Open Send File");
  324.     return FALSE;
  325.     }
  326.     else
  327.     InfoMsg1Line("XMODEM Send, <esc> from VT100 window to abort");
  328.     attempts = 0;
  329.     sectnum = 1;
  330.     No_XON();
  331.     /* wait for sync char */
  332.     j=1;
  333.     while (((c = readchar()) != NAK) && (j++ < ERRORMAX))
  334.     if (timeout == USERABORT) { Do_XON(); return(FALSE); }
  335.     if (j >= (ERRORMAX))
  336.     {
  337.     InfoMsg1Line("XMODEM: Receiver not sending NAKs");
  338.     Do_XON();
  339.     return FALSE;
  340.     }
  341.  
  342.     while ((bytes_to_send = read(fd, bufr, BufSize)) &&
  343.         attempts != RETRYMAX)
  344.     {
  345.     if (bytes_to_send == EOF)
  346.         {
  347.         InfoMsg1Line("XMODEM: Error Reading File");
  348.         Do_XON();
  349.         return FALSE;
  350.         }
  351.  
  352.     bufptr = 0;
  353.     while (bytes_to_send > 0 && attempts != RETRYMAX)
  354.         {
  355.         attempts = 0;
  356.         sprintf(scrstr2,"Sending block %4d",sectnum);
  357. #ifdef BUGFIXES
  358.         size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
  359.         bytes_to_send -= size;
  360. #endif
  361.         do {
  362.         InfoMsgNoScroll(scrstr2);
  363.         sendchar(SOH);
  364.         sendchar(sectnum);
  365.         sendchar(~sectnum);
  366.         checksum = 0;
  367. #ifdef BUGFIXES
  368.         for (j = bufptr; j < bufptr + size; j++)
  369.             {
  370.             sendchar(bufr[j]);        /* send buffer data */
  371. #else
  372.         size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
  373.         bytes_to_send -= size;
  374.         for (j = bufptr; j < (bufptr + SECSIZ); j++)
  375.         if (j < (bufptr + size)) {
  376.             sendchar(bufr[j]);
  377. #endif
  378.             checksum += bufr[j];
  379.             }
  380. #ifdef BUGFIXES
  381.         if( size < SECSIZ )        /* check if we need to pad */
  382.             {
  383.             c = bufr[j-1] ? 0 : 0x1A;    /* choose correct padding */
  384.             j = SECSIZ - size;
  385.             checksum += j * c;
  386.             while ( j-- )
  387.             sendchar(c);        /* send padding */
  388.             }
  389. #else
  390.         else sendchar(0);
  391. #endif
  392.         sendchar(checksum);
  393.         attempts++;
  394.         c = readchar();
  395.         if (timeout == USERABORT) {
  396.             InfoMsg1Line("XMODEM: ABORTED");
  397.             Do_XON();
  398.             return FALSE;
  399.             }
  400.         } while ((c != ACK) && (attempts != RETRYMAX));
  401.         bufptr += size;
  402.         bytes_xferred += size;
  403.         sprintf(scrstr2,"Sent    block %4d",sectnum);
  404.         InfoMsgNoScroll(scrstr2);
  405.         sectnum++;
  406.         }
  407.     }
  408.     close(fd);
  409.     if (attempts == RETRYMAX)
  410.     {
  411.     InfoMsg1Line("XMODEM: No Acknowledgment, ABORTING");
  412.     Do_XON();
  413.     return FALSE;
  414.     }
  415.     else
  416.     {
  417.     attempts = 0;
  418.     do {
  419.         sendchar(EOT);
  420.         attempts++;
  421.         } while ((readchar() != ACK) &&
  422.              (attempts != RETRYMAX) &&
  423.              (timeout != USERABORT)) ;
  424.     if (attempts == RETRYMAX)
  425.         InfoMsg1Line("XMODEM: No end of file");
  426.     }
  427.     Do_XON();
  428.     ScrollInfoMsg(1);
  429.     return TRUE;
  430.     }
  431.  
  432. /* allow for multi file xfers separated by commas under
  433.     kermit and XMODEM */
  434.  
  435. void multi_xfer(name,mode,do_send)
  436. char *name;
  437. int (*mode)();
  438. int do_send;
  439.     {
  440.     int done = 0;
  441.     int status;
  442.     char *p, *name_start;
  443.  
  444.     timeout = USERABORT - 1;
  445.     for(p=name_start=name; !done && timeout != USERABORT; name_start=++p)
  446.     {
  447.     if (*(name_start) == '$' && *(name_start+1) == '\0') {
  448.         saybye();
  449.         return;
  450.         }
  451.     while(*p == ' ') p++;
  452.     while(*p && *p != ',' && *p != ' ') p++;
  453.     if (*p == '\0') {
  454.         done = TRUE;
  455.         multi = 0;
  456.     }
  457.     else
  458.         multi = 1;
  459.     *p = '\0';
  460.  
  461.     status = ((*mode)(name_start, multi));
  462.     if (status == FALSE) close(fd);
  463.     }
  464.     server = 0;
  465.     multi = 0;
  466.     }
  467.  
  468.