home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file contains most of the private modules used to send files
- * using XMODEM protocols. The modules that are not present in this
- * file are in _XMODEMC.C, which contains routines that are common to
- * both the send and receive drivers.
- *
- * The Greenleaf Comm Library
- *
- * Copyright (C) 1989-90 Greenleaf Software Inc. All Rights Reserved.
- *
- */
- #define LINT_ARGS
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "gf.h"
- #include "asiports.h"
- #include "xfer.h"
- #include "_xfer.h"
-
- /*
- * void _XmodemSend(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * This is the main module for the XMODEM transfer routine. It is in
- * charge of doing it all.
- *
- * SIDE EFFECTS
- *
- * A file may have been transfered.
- *
- * RETURNS
- *
- * The return from this program is in the xmodem parameter block
- * return status structure element. It is one of the XFER_RETURN
- * codes defined in XFER.H.
- *
- * AUTHOR
- * Mark Nelson 28-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- void GF_CONV _XmodemSend(XFER *xmodem)
- {
- int done;
- int status;
-
- xmodem->sending=TRUE;
- if (!_XferInitialize(xmodem)) /* Here is where I initialize the */
- return; /* xmodem parameter block to set the */
- xmodem->block_number=1L; /* whole thing in motions. */
- if (!_XferOpenFile(xmodem)) /* Now I open the file */
- return;
- if (!_XmodemGetFirstNAK(xmodem)) /* I wait for the first NAK before I */
- { /* can start sending stuff. */
- _XferCleanup(xmodem);
- return;
- }
- if (!_XmodemReadNextFileBlock(xmodem)) /* Now I read in a block from the */
- { /* file to "prime the pump" */
- xmodem->return_status=XFER_RETURN_FILE_ERROR;
- _XferCleanup(xmodem);
- return;
- }
- done=FALSE;
- while (!done) /* Now I sit in this loop until */
- { /* there is no more data to send*/
- if (xmodem->current_block_size != 0) /* or a fatal error occurs */
- status=_XmodemSendBlock(xmodem);
- else
- {
- _XferMessage(xmodem,"File transmission complete");
- status=_XmodemSendEOT(xmodem);
- }
- if (!status) /* After sending the block, I */
- { /* check the returned status. */
- _XferCleanup(xmodem);
- return;
- }
- if (_XmodemGetACK(xmodem)) /* Now I try to get an ACK */
- { /* If I get one, I either */
- if (xmodem->current_block_size==0) /* read in the next block, */
- done=TRUE; /* or set things up to exit*/
- else
- _XmodemReadNextFileBlock(xmodem);
- }
- else if (xmodem->return_status == XFER_RETURN_SUCCESS)
- {
- xmodem->error_count++; /* If I didn't get */
- if (xmodem->error_count >= XMODEM_MAX_ERRORS) /* an ACK I handle */
- { /* the error. */
- _XferMessage(xmodem,"Exceeded maximum error count");
- xmodem->return_status=XFER_RETURN_TOO_MANY_ERRORS;
- done=TRUE;
- }
- }
- else
- done=TRUE;
- }
- _XferCleanup(xmodem); /* Clean everything up when done */
- }
-
- /*
- * void _YmodemSend(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * Sending a bunch of files using YMODEM consists of repeating two
- * operations over and over. First, a single block 0 is sent, containing
- * the file name and size. Then, a standard XMODEM-1K transfer is performed.
- * This sequence is repeated until there are no more files left to send,
- * when an empty file name is sent.
- *
- * SIDE EFFECTS
- *
- * A file may have been transfered.
- *
- * RETURNS
- *
- * The return from this program is in the xmodem parameter block
- * return status structure element. It is one of the XFER_RETURN
- * codes defined in XFER.H.
- *
- * AUTHOR
- * Mark Nelson 28-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- void GF_CONV _YmodemSend(XFER *xmodem)
- {
- XFER ymodem;
- int done;
- int i;
- char *filename_list;
- char *saved_xmodem_filename;
- char current_filename[81];
- FILE *temp_file;
-
- ymodem=*xmodem; /* I set up a ymodem parameter */
- filename_list=xmodem->filename; /* block that is used to send */
- saved_xmodem_filename=xmodem->filename; /* file name in block 0. That */
- xmodem->filename=current_filename; /* set up is all done here. */
- ymodem.filename=NULL; /* The filename passed here in */
- ymodem.sending=TRUE; /* the xmodem parameter block is*/
- /* potentially a list of files, */
- /* and I save off a pointer to */
- if (!_XferInitialize(&ymodem)) /* it for storage. */
- return;
- done=FALSE;
-
- while (!done)
- {
- /* At the start of the loop I need */
- ymodem.current_block_number=0; /* to send the block 0 with the */
- ymodem.block_number=0L; /* filename in it. */
- ymodem.current_block_size=128;
- for (i=0;i<128;i++) /* I start by filling the block 0 */
- ymodem.buffer[i]=0; /* with nulls */
-
- if (!_XmodemGetFirstNAK(&ymodem)) /* I try to get the first NAK so I */
- break; /* can send the filename */
- /*
- * All this code with the filename list is done to copy a single filename
- * into the current_filename[] array. The ';', ',', and ' ' characters are
- * valid separators for the list of filenames.
- */
- i=0;
- while (*filename_list != ';' && *filename_list != ',' &&
- *filename_list != ' ' && *filename_list != '\0')
- current_filename[i++]=*filename_list++;
- while (*filename_list==';' || *filename_list==',' || *filename_list == ' ')
- filename_list++;
- current_filename[i]='\0';
-
- if (i == 0)
- { /* If i is 0, it means */
- done=TRUE; /* there are no more file */
- /* names. I still need to */
- } /* send a block full of */
- strcpy(ymodem.buffer,current_filename); /* Nulls, but I set the */
- /* done flag so I will drop*/
- /* out of this loop after */
- /* I send block 0 */
-
- if (! done ) {
- temp_file = fopen(current_filename,"rb");
- if ( temp_file == NULL )
- break;
- fseek( temp_file, 0L, SEEK_END );
- sprintf( ymodem.buffer+strlen( current_filename ) + 1,
- "%ld",
- ftell( temp_file ) );
- fclose( temp_file );
- }
- if (!_XmodemSendBlock(&ymodem))
- break;
- if (!_XmodemGetACK(&ymodem)) /* After sending my block 0, I need*/
- break; /* to get an ACK fro the far end */
-
- if (!done) /* If there is a file to send, I do*/
- { /* it here, breaking if the send */
- _XmodemSend(xmodem); /* failed for one reason or another*/
- if (xmodem->return_status != XFER_RETURN_SUCCESS)
- break;
- }
- }
- _XferCleanup(&ymodem); /* Cleanup and exit. Note that */
- xmodem->filename=saved_xmodem_filename; /* when I exit, I make sure the */
- } /* parameter block that got */
- /* sent to me still points to the*/
- /* filename list. */
-
-
- /*
- * int _XmodemSendBlock(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * This is the main routine that is called to send an xmodem data block.
- * It doesn't really do anything on its own. Instead, it calls subroutines
- * to send the start character, block number, data, and checksum. Note
- * that this routine assumes that we are free to send, having already
- * received an ACK or NAK.
- *
- * SIDE EFFECTS
- *
- * A block is sent, and we should wait for an ACK.
- *
- * RETURNS
- *
- * The return from this program is in the xmodem parameter block
- * return status structure element. It is one of the XFER_RETURN
- * codes defined in XFER.H. If the send was successful, this routine
- * returns a TRUE, else it returns a FALSE.
- *
- * AUTHOR
- * Mark Nelson 29-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- int GF_CONV _XmodemSendBlock(XFER *xmodem)
- {
- /*
- * This is one of the basic points where we call the user defined print guy.
- */
- if ( xmodem->block_number != 0 )
- _XferMessage(xmodem,"Sending block %ld",xmodem->block_number-1);
- else
- _XferMessage(xmodem,"Sending YMODEM startup block");
-
- if (!_XmodemSendStartCharacter(xmodem)) /* First, I send either an SOH */
- return(FALSE); /* or STX, depending on the size*/
- /* of the output block. */
-
- if (!_XmodemSendBlockNumber(xmodem)) /* Then I send the block number */
- return(FALSE); /* and its inverse. */
-
- if (!_XmodemSendBuffer(xmodem)) /* Then I send all of the data */
- return(FALSE); /* bytes, either 128 or 1024. */
-
- if (!_XmodemSendChecksum(xmodem)) /* Finally, send either the CRC */
- return(FALSE); /* or additive checksum. */
-
- return(TRUE);
- }
-
- /*
- * int _XmodemSendChecksum(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * This routine is charged with sending out the checksum for a given
- * data block. This routine takes one of two approaches, one for 16 bit
- * CRC checksums, which are sent out in two bytes, and the other for eight
- * bit additive checksums, which are sent out in one byte. The two routines
- * both calculate the checksum, then send it.
- *
- * SIDE EFFECTS
- *
- *
- * RETURNS
- *
- * The return from this program is in the xmodem parameter block
- * return status structure element. It is one of the XFER_RETURN
- * codes defined in XFER.H. If the send was successful, this routine
- * returns a TRUE, else it returns a FALSE.
- *
- * AUTHOR
- * Mark Nelson 29-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- int GF_CONV _XmodemSendChecksum(XFER *xmodem)
- {
- int i;
- int stat_1;
- int stat_2; /* If I am in CRC mode, I perform the 16 */
- /* bit CRC calculation, then send out */
- if (xmodem->x.xmodem.crc_mode) /* the two bytes. */
- {
- xmodem->current_block_checksum=glcrc(xmodem->current_block_size,0,xmodem->buffer);
- stat_1=asiputc(xmodem->port,(xmodem->current_block_checksum >> 8) & 0xff);
- stat_2=asiputc(xmodem->port,xmodem->current_block_checksum & 0xff);
- }
- else /* If I am in addititive checksum mode, I add up */
- { /* all the bytes and send out the checksum. */
- xmodem->current_block_checksum=0;
- for (i=0;i<xmodem->current_block_size;i++)
- xmodem->current_block_checksum += xmodem->buffer[i];
- stat_1=asiputc(xmodem->port,xmodem->current_block_checksum & 0xff);
- stat_2=ASSUCCESS;
- }
- /*
- * If either of the bytes sent out caused an error, we flag the error in the
- * parameter block and return a FALSE to the calling routine.
- */
- if (stat_1 != ASSUCCESS || stat_2 != ASSUCCESS)
- {
- _XferMessage(xmodem,"Error sending checksum");
- xmodem->return_status=XFER_RETURN_CANT_PUT_BUFFER;
- return(FALSE);
- }
- return(TRUE); /* Else return TRUE, everything is great. */
- }
-
- /*
- * int _XmodemSendBlockNumber(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * This routine has a real simple job. It sends the block number for
- * the current XFER block. Because of the way XMODEM works, this means
- * sending the block number once, then sending its inverse.
- *
- * SIDE EFFECTS
- *
- *
- * RETURNS
- *
- * The return from this program is in the xmodem parameter block
- * return status structure element. It is one of the XFER_RETURN
- * codes defined in XFER.H. If the send was successful, this routine
- * returns a TRUE, else it returns a FALSE.
- *
- * AUTHOR
- * Mark Nelson 29-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- int GF_CONV _XmodemSendBlockNumber(XFER *xmodem)
- {
- int stat_1;
- int stat_2;
- /*
- * Sending the two block number bytes is pretty straightforward. By the way,
- * the values in current_block_number were put there when the block of data
- * was read in from the file.
- */
- stat_1=asiputc(xmodem->port,xmodem->current_block_number);
- stat_2=asiputc(xmodem->port,~xmodem->current_block_number);
- /*
- * If either of the asiputc() operations caused an error, it is time to
- * flag it, and return a FALSE.
- */
- if (stat_1 != ASSUCCESS || stat_2 != ASSUCCESS)
- {
- _XferMessage(xmodem,"Error sending block number");
- xmodem->return_status=XFER_RETURN_CANT_PUT_BUFFER;
- return(FALSE);
- }
- return(TRUE); /* Everything went okay, so I can return a TRUE. */
- }
-
- /*
- * int _XmodemSendStartCharacter(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * This routine has a real simple job. It sends the start character for
- * the current XMODEM block. About the only thing it has to do is
- * figure out whether to send an SOH or an STX, and all that requires is
- * a quick peek at the block size.
- *
- * SIDE EFFECTS
- *
- *
- * RETURNS
- *
- * The return from this program is in the xmodem parameter block
- * return status structure element. It is one of the XFER_RETURN
- * codes defined in XFER.H. If the send was successful, this routine
- * returns a TRUE, else it returns a FALSE.
- *
- * AUTHOR
- * Mark Nelson 29-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- int GF_CONV _XmodemSendStartCharacter(XFER *xmodem)
- {
- int stat;
-
- if (xmodem->current_block_size==128) /* Here I send an SOH or STX, */
- stat=asiputc(xmodem->port,SOH); /* depending on the block size. */
- else /* The block size was set up when */
- stat=asiputc(xmodem->port,STX); /* the current file block was read*/
- /*
- * Here is where I flag an error if one occurred when I sent the start char.
- */
- if (stat != ASSUCCESS)
- {
- _XferMessage(xmodem,"Error sending first character");
- xmodem->return_status=XFER_RETURN_CANT_PUT_BUFFER;
- return(FALSE);
- }
- return(TRUE);
- }
-
- /*
- * int _XmodemSendBuffer(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * This routine has the job of sending out all the characters in the current
- * data buffer. It also watches for errors while it does it.
- *
- * SIDE EFFECTS
- *
- *
- * RETURNS
- *
- * The return from this program is in the xmodem parameter block
- * return status structure element. It is one of the XFER_RETURN
- * codes defined in XFER.H. If the send was successful, this routine
- * returns a TRUE, else it returns a FALSE.
- *
- * AUTHOR
- * Mark Nelson 29-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- int GF_CONV _XmodemSendBuffer(XFER *xmodem)
- {
- int i;
-
- for (i=0;i<xmodem->current_block_size;i++)
- {
- if (asiputc(xmodem->port,xmodem->buffer[i]) != ASSUCCESS)
- {
- _XferMessage(xmodem,"Error sending buffer");
- xmodem->return_status=XFER_RETURN_CANT_PUT_BUFFER;
- return(FALSE);
- }
- }
- return(TRUE);
- }
-
- /*
- * int _XmodemGetFirstNAK(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * This piece of code has the tough job of reading in the first NAK. When
- * the protocol is just getting started, the sender has to wait for the
- * receive to send a NAK character to get the ball rolling. In addition,
- * the sender has to figure out some stuff about what version of the XMODEM
- * protocol to use depending on the received NAK character.
- *
- * SIDE EFFECTS
- *
- * This routine may override the senders desire to use the CRC 16 bit
- * checksum protocol, changing back to additive checksum mode.
- *
- * RETURNS
- *
- * The return from this program is in the xmodem parameter block
- * return status structure element. It is one of the XFER_RETURN
- * codes defined in XFER.H. If any of several errors occur, the
- * routine returns a FALSE, which means abort the program. Otherwise
- * it returns a TRUE.
- *
- * AUTHOR
- * Mark Nelson 29-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- int GF_CONV _XmodemGetFirstNAK(XFER *xmodem)
- {
- int timeout_timer;
- int last_char;
- int c;
- /*
- * I sit in this giant for loop forever. The only way out of it is with
- * a return statement. While in the loop, many errors will cause a drop
- * down towards the end of the loop. At the end, I bump the error counter
- * and check it to see if we have maxed out. Exceeding the maximum error
- * count causes an abort.
- */
- for ( ; ; )
- {
- timeout_timer=XMODEM_RECEIVE_TIMEOUT; /* The first thing I do*/
- while ((c=asigetc_timed(xmodem->port,18)) < 0) /* is wait to get any */
- { /* char from my port. I can*/
- if (_XferAbortKeyPressed(xmodem)) /* drop out of this loop by*/
- return(FALSE); /* the abort key, a char, */
- if (--timeout_timer == 0) /* or a timeout. */
- break;
- }
- if (timeout_timer) /* If I didn't time out, I */
- { /* go down here and check */
- /* out my input char. Else*/
- /* I fall down and check */
- /* my error counters out. */
- last_char=xmodem->x.xmodem.last_control_char;
- xmodem->x.xmodem.last_control_char=c;
- switch (c) /* Here is where I process */
- { /* the input character. */
-
- case CAN : /* A pair of CANs means */
- /* the remote end wants */
- if (last_char==CAN) /* to abort. Look for it*/
- {
- xmodem->return_status=XFER_RETURN_REMOTE_ABORT;
- _XferMessage(xmodem,"Remote end sent cancel code");
- return(FALSE);
- }
- break;
- /* When waiting for the*/
- case NAK : /* first NAK, a NAK */
- /* means the receiver */
- if (xmodem->x.xmodem.crc_mode) /* can't deal with CRC */
- {
- _XferMessage(xmodem,"Falling back to checksum mode");
- xmodem->x.xmodem.crc_mode=FALSE;
- }
- return(TRUE);
- case 'C' : /* A C char means I can */
- /* send 1K blocks, but */
- if (xmodem->x.xmodem.crc_mode) /* not in X/YMODEM-1K-G */
- if (xmodem->transfer_type < XFER_TYPE_XMODEM_1KG)
- return(TRUE); /* If this is okay, I */
- break; /* return TRUE, else */
- /* I fall through to the*/
- /* error code. */
-
- case 'G' : /* A G is okay for the */
- /* two -G protocols. */
- if (xmodem->transfer_type >= XFER_TYPE_XMODEM_1KG)
- return(TRUE);
- break;
- /* If I get a 'funny' first character, I assume*/
- default : /* it is time to flush the input buffer. */
- while (asigetc_timed(xmodem->port,18) >= 0)
- if (_XferAbortKeyPressed(xmodem))
- return(FALSE);
- break;
- }
- } /* I fall down here when*/
- xmodem->error_count++; /* I get a bad char. I */
- /* bump the error count,*/
- if (xmodem->error_count >= XMODEM_MAX_ERRORS)/* and exit if things */
- { /* are too bad. */
- xmodem->return_status=XFER_RETURN_PACKET_TIMEOUT;
- return(FALSE);
- }
- }
- }
-
- /*
- * int _XmodemReadNextFileBlock(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * This piece of code is called when the last buffer has been sent and
- * acked properly. It means it is time to load up a new buffer. It
- * has a few decisions to make. First, it has to decide whether to send
- * a 128 or 1024 byte buffer. Next, it needs to check for end of file.
- * That's about it.
- *
- * SIDE EFFECTS
- *
- *
- * RETURNS
- *
- * This module returns a FALSE if an EOF is reached, otherwise a TRUE.
- *
- * AUTHOR
- * Mark Nelson 29-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- int GF_CONV _XmodemReadNextFileBlock(XFER *xmodem)
- {
- int bytes_read;
- int i;
- /*
- * This module is responsible for setting the current_block_size parameter
- * for everyone else to use later on. It also has to update the
- * current_block_number, block_number, and byte_count fields.
- */
- xmodem->current_block_size=128;
- /*
- * If I am using 1K blocks and I have at least a buffer full, I load up 1K
- */
- if ((xmodem->file_length - xmodem->byte_count) > 896 &&
- xmodem->transfer_type != XFER_TYPE_XMODEM)
- xmodem->current_block_size=1024;
- bytes_read=fread(xmodem->buffer,1,xmodem->current_block_size,xmodem->file);
- if (bytes_read==0)
- {
- xmodem->current_block_size=0;
- return(FALSE); /* This is an EOF, everything is OK*/
- } else if (bytes_read < xmodem->current_block_size )
- {
- for (i=bytes_read;i<xmodem->current_block_size;i++)
- xmodem->buffer[i]='\0';
- }
- xmodem->current_block_number= (int) xmodem->block_number & 0xff;
- xmodem->block_number++;
- xmodem->byte_count += bytes_read;
- return(TRUE);
- }
-
- /*
- * int _XmodemGetACK(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * After a buffer is sent, it is the job of this routine to wait for the
- * remote end to send an ACK. This piece of code gets pretty bad,
- * because it has to handle a whole bunch of different possibilities.
- * Look to the code for explanations.
- *
- *
- * SIDE EFFECTS
- *
- *
- * RETURNS
- *
- * This module returns a FALSE if a valid ACK was not received. The calling
- * program has to look at the return_status structure element to see if
- * a fatal error occurred, or if he should just retry. If a TRUE is returned,
- * it means everything is ready to send the next block.
- *
- * AUTHOR
- * Mark Nelson 29-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- int GF_CONV _XmodemGetACK(XFER *xmodem)
- {
- int timeout_timer;
- int last_char;
- int c;
-
- while (!istxempty(xmodem->port)) /* The first thing this routine */
- { /* does is wait for the output */
- if (_XferAbortKeyPressed(xmodem)) /* buffer to empty. It wouldn't */
- return(FALSE); /* be fair to start the timeout */
- } /* timer up until all the chars */
- /* have been sent to the far end.*/
- /*
- * This is another one of those while loops that can only be exited via
- * a return statement.
- */
- for ( ; ; )
- {
- /*
- * If I am sending with one of the "-G" protocols, and this is a data block,
- * I don't wait for an ACK. But there is always the possibility that the
- * far end will send an ACK, so I only return immediately if the receive
- * buffer is empty. Else I process any incoming chars, which could be
- * a NAK, or maybe a CAN-CAN.
- */
- if (xmodem->current_block_size != 0)
- if (xmodem->transfer_type==XFER_TYPE_XMODEM_1KG ||
- xmodem->transfer_type==XFER_TYPE_YMODEM_G)
- if (isrxempty(xmodem->port))
- return(TRUE);
-
- timeout_timer=XMODEM_ACK_TIMEOUT; /* Here I sit waiting */
- while ((c=asigetc_timed(xmodem->port,18)) < 0) /* for a char. One of*/
- { /* 3 things can happen. I */
- if (_XferAbortKeyPressed(xmodem)) /* can get a char, an abort*/
- return(FALSE); /* key, or a timeout. */
- if (--timeout_timer == 0)
- break;
- }
- if (timeout_timer==0) /* If I timed out, it isn't a fatal error, */
- return(FALSE); /* it is an error. Return the error flag and*/
- /* let the caller figure out what to do with */
- /* it. */
-
- last_char=xmodem->x.xmodem.last_control_char;
- xmodem->x.xmodem.last_control_char=c;
- /*
- * Now that I have an input character, it is time to decide what to do
- * with it. I process all possiblities in this switch statement, and
- * return either a TRUE or FALSE.
- */
- switch (c)
- {
- /*
- * Even a single CAN is a fatal error for the "-G" protocols. For
- * everyone else, it takes a CAN-CAN to cause a fatal error. Otherwise it
- * is a non-fatal error.
- */
- case CAN :
- if (xmodem->transfer_type==XFER_TYPE_XMODEM_1KG ||
- xmodem->transfer_type==XFER_TYPE_YMODEM_G)
- xmodem->return_status=XFER_RETURN_REMOTE_ABORT;
- if (last_char==CAN)
- xmodem->return_status=XFER_RETURN_REMOTE_ABORT;
- return(FALSE);
- /*
- * A NAK is a fatal error for a "-G" family transfer. For everyone else
- * it is a non-fatal error, which gets flagged back to the caller.
- */
- case NAK :
- if (xmodem->transfer_type==XFER_TYPE_XMODEM_1KG ||
- xmodem->transfer_type==XFER_TYPE_YMODEM_G)
- xmodem->return_status=XFER_RETURN_REMOTE_ABORT;
- return(FALSE);
- /*
- * An ACK is a success story for everyone, unconditionally.
- */
- case ACK :
- return(TRUE);
- /*
- * In the event of a "funny" character, I flush the input buffer, and
- * return an error.
- */
- default :
- while (asigetc_timed(xmodem->port,18) >= 0)
- if (_XferAbortKeyPressed(xmodem))
- return(FALSE);
- return(FALSE);
- }
- }
- }
-
-
- /*
- * int _XmodemSendEOT(XFER *xmodem)
- *
- * ARGUMENTS
- *
- * xmodem: A pointer to the parameter block used to perform the
- * transfer.
- *
- * DESCRIPTION
- *
- * Sending an EOT is pretty simple. I just have to check for any transmission
- * error after sending the character.
- *
- *
- * SIDE EFFECTS
- *
- *
- * RETURNS
- *
- * This module returns a FALSE if the EOT wouldn't go. This is a fatal error
- * as flagged in the return_status structure element. Otherwise a TRUE
- * is returned to the calling program.
- *
- * AUTHOR
- * Mark Nelson 29-Aug-1989 20:57:40.92
- *
- * MODIFICATIONS
- *
- */
-
- int GF_CONV _XmodemSendEOT(XFER *xmodem)
- {
- if (asiputc(xmodem->port,EOT)==ASSUCCESS)
- return(TRUE);
- xmodem->return_status=XFER_RETURN_CANT_SEND_EOT;
- return(FALSE);
- }
-