home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
066.lha
/
Zterm
/
xmodem.c
< prev
next >
Wrap
Text File
|
1986-11-20
|
17KB
|
605 lines
/* Create xrb - xmodem_request_block */
/* Xmodem, and associated routines for z-term */
/* Nik Conwell 4/20/87 */
#include "term.h" /* Defines */
#include "term.common"
/* Send a character to the serial port */
void sendchar(ch,zt)
char ch;
struct Z_Term *zt;
{
zt->rs_out = ch;
DoIO(zt->write_request);
}
int readchar(ch,zt)
char *ch;
struct Z_Term *zt;
{
set_timer(zt->timeout_time,zt); /* set up the timer */
dowait: zt->wakeupmask = Wait(SERIAL_INPUT |
W1_INTUITION_MESSAGE |
TIMER_MESSAGE);
if (zt->wakeupmask & SERIAL_INPUT)
{
WaitIO(zt->read_request);
*ch = zt->rs_in;
BeginIO(zt->read_request);
} /* end if */
if (zt->wakeupmask & W1_INTUITION_MESSAGE)
{
zt->message = (struct IntuiMessage *) GetMsg(zt->w1->UserPort);
zt->class = zt->message->Class;
zt->code = zt->message->Code;
ReplyMsg(zt->message);
if ((zt->class == MENUPICK) && (zt->code != MENUNULL))
{
zt->menunum = MENUNUM(zt->code);
zt->menuitem = ITEMNUM(zt->code);
if ((zt->menunum == MENU_FILESTUFF) &&
(zt->menuitem == MENU_FILESTUFF_ABORT_XMODEM))
{
con_put_str("\nUser Cancelled Transfer.\n",zt);
return(USER_ABORT);
}
} /* end if the user is playing with the menu */
goto dowait;
} /* end if we woke up because of intuition */
if (zt->wakeupmask & TIMER_MESSAGE)
{
con_put_str("\nTimeout waiting for character.\n",zt);
return(TIMEOUT);
}
return(NULL);
}
int xmodem_read_file(zt)
struct Z_Term *zt;
{
int sectnum, errors, errorflag;
unsigned int checksum, i, j, bufptr;
unsigned char sectcurr, sectcomp, sentchecksum1, sentchecksum2;
unsigned char ourchecksum1, ourchecksum2, firstchar;
int xfer_current_blocksize, xfer_current_error_detect_alg;
int fd;
char numb[10];
char bufr[BUFSIZE];
int temp;
firstchar = NULL;
sectcurr = NULL;
sectcomp = NULL;
sentchecksum1 = NULL;
sentchecksum2 = NULL;
xfer_current_blocksize = zt->xfer_blocksize; /* copy blocksize */
xfer_current_error_detect_alg = zt->xfer_error_detect_alg; /* copy spec alg */
if ((fd = creat(zt->filename, 0)) < 0)
{
con_put_str("\nCannot Open ",zt);
con_put_str(zt->filename,zt);
con_put_str(" . File exists.\n",zt);
goto xmodem_read_file_exit;
}
else
{
con_put_str("\nReceiving ",zt);
con_put_str(zt->filename,zt);
con_put_str(" using ",zt);
if (zt->xfer_blocksize == XMODEM_128_BLOCK)
{
con_put_str("128",zt);
}
if (zt->xfer_blocksize == XMODEM_1024_BLOCK)
{
con_put_str("1024",zt);
}
con_put_str(" byte blocks, with ",zt);
if (zt->xfer_error_detect_alg == XMODEM_CHECKSUM)
{
con_put_str("checksum",zt);
}
if (zt->xfer_error_detect_alg == XMODEM_CRC16)
{
con_put_str("crc-16",zt);
}
con_put_str(" error detection algorithm.\n",zt);
}
zt->timeout_time = 3;
sectnum = errors = bufptr = 0;
do /* Loop until SOH or STX is received */
{
if (xfer_current_error_detect_alg == XMODEM_CHECKSUM)
{
sendchar((char) NAK,zt); /* NAK specifies checksum recv */
}
if (xfer_current_error_detect_alg == XMODEM_CRC16)
{
sendchar((char) CCHAR,zt); /* C specifies crc16 recv */
}
zt->st = readchar(&firstchar,zt);
if (zt->st == USER_ABORT)
{
goto xmodem_read_file_exit;
}
if ((zt->st == TIMEOUT) && (xfer_current_error_detect_alg == XMODEM_CHECKSUM))
{
con_put_str("\nSender not responding to initial NAK.\n",zt);
goto xmodem_read_file_exit; /* if checksum, getout */
}
if ((zt->st == TIMEOUT) && (xfer_current_error_detect_alg == XMODEM_CRC16))
{
xfer_current_error_detect_alg = XMODEM_CHECKSUM;
con_put_str("\nSender not responding to CRC option.\n",zt);
con_put_str("\nXferring using checksum algorithm.\n",zt);
}
if ((firstchar != SOH) && (firstchar != STX)) /* if !SOH, tell what it is */
{
con_put_str("\nSender not sending SOH or STX.\n",zt);
temp = (int) firstchar;
stci_d(numb,temp,10);
con_put_str(numb,zt);
con_put_str(" ascii received instead.\n",zt);
}
}
while ((firstchar != SOH) && (firstchar != STX));
zt->timeout_time = 10; /* 10 second timeout period */
while ((firstchar != EOT) && (errors < ERRORMAX))
{
errorflag = FALSE;
if ((firstchar == SOH) || (firstchar == STX))
{
if ((firstchar == SOH) && (xfer_current_blocksize == XMODEM_1024_BLOCK))
{
xfer_current_blocksize = XMODEM_128_BLOCK;
con_put_str("\nSender specified 128 byte block.\n",zt);
con_put_str("Temporarily switched block size.\n",zt);
}
if ((firstchar == STX) && (xfer_current_blocksize == XMODEM_128_BLOCK))
{
xfer_current_blocksize = XMODEM_1024_BLOCK;
con_put_str("\nSender specified 1024 byte block.\n",zt);
con_put_str("Temporarily switched block size.\n",zt);
}
con_put_str("Receiving Block ",zt);
stci_d(numb,sectnum,10);
con_put_str(numb,zt);
con_put_str("...",zt);
zt->st = readchar(§curr,zt);
if (zt->st == USER_ABORT)
{
goto xmodem_read_file_exit;
}
if (zt->st == TIMEOUT)
{
con_put_str("\nTimeout occured while waiting for sectcurr.\n",zt);
goto xmodem_read_file_exit;
}
zt->st = readchar(§comp,zt);
if (zt->st == USER_ABORT)
{
goto xmodem_read_file_exit;
}
if (zt->st == TIMEOUT)
{
con_put_str("\nTimeout occured while waiting for sector complement.\n",zt);
goto xmodem_read_file_exit;
}
if ((sectcurr + sectcomp) == 255) /* must be compliment */
{
if (sectcurr == (sectnum + 1 & 0xff)) /* must be same sector */
{
checksum = 0;
for (j = bufptr; j < (bufptr + xfer_current_blocksize); j++)
{
zt->st = readchar((char *) &bufr[j],zt);
if (zt->st == USER_ABORT)
{
goto xmodem_read_file_exit;
}
if (zt->st == TIMEOUT)
{
con_put_str("\nTimeout occurred waiting for data in block.\n",zt);
goto xmodem_read_file_exit;
}
if (xfer_current_error_detect_alg == XMODEM_CHECKSUM) /* calc checksum */
{
checksum = (checksum + bufr[j]) & 0xff;
}
if (xfer_current_error_detect_alg == XMODEM_CRC16)
{
checksum = checksum ^ (int) bufr[j] << 8; /* calc crc16 */
for (i = 0;i < 8; ++i)
{
if (checksum & 0x8000)
{
checksum = checksum << 1 ^ 0x1021;
}
else
{
checksum = checksum << 1;
}
} /* end for */
checksum = checksum & 0xffff;
} /* end if error detect alg == XMODEM_CRC16 */
} /* end for */
if (zt->xfer_error_detect_alg == XMODEM_CHECKSUM)
{
zt->st = readchar(&sentchecksum1,zt);
if (zt->st == USER_ABORT)
{
goto xmodem_read_file_exit;
}
ourchecksum1 = checksum;
}
if (xfer_current_error_detect_alg == XMODEM_CRC16)
{
zt->st = readchar(&sentchecksum1,zt);
if (zt->st == USER_ABORT)
{
goto xmodem_read_file_exit;
}
zt->st = readchar(&sentchecksum2,zt);
if (zt->st == USER_ABORT)
{
goto xmodem_read_file_exit;
}
ourchecksum1 = checksum >> 8;
ourchecksum2 = checksum;
}
if (((xfer_current_error_detect_alg == XMODEM_CHECKSUM) &&
(ourchecksum1 == sentchecksum1)) ||
((xfer_current_error_detect_alg == XMODEM_CRC16) &&
(ourchecksum1 == sentchecksum1) &&
(ourchecksum2 == sentchecksum2)))
{
errors = 0;
sectnum++;
bufptr += xfer_current_blocksize;
con_put_str("ok\n",zt);
if (bufptr == BUFSIZE)
{
bufptr = 0;
if (write(fd, bufr, BUFSIZE) == EOF)
{
con_put_str("\nError Writing File\n",zt);
goto xmodem_read_file_exit;
} /* end if */
} /* end if */
sendchar((char) ACK,zt);
} /* end if */
else /* checksum not what we computed!!! */
{
errorflag = TRUE;
if (zt->st == TIMEOUT)
{
goto xmodem_read_file_exit;
}
con_put_str("\nCalculated checksum != received checksum.\n",zt);
con_put_str("\nCalculated checksum1 = ",zt);
stci_d(numb,(int) ourchecksum1,10);
con_put_str(numb,zt);
con_put_str(". Received checksum1 = ",zt);
stci_d(numb,(int) sentchecksum1,10);
con_put_str(numb,zt);
con_put_str(".\n",zt);
if (xfer_current_error_detect_alg == XMODEM_CRC16)
{
con_put_str("\nCalculated checksum2 = ",zt);
stci_d(numb,(int) ourchecksum2,10);
con_put_str(numb,zt);
con_put_str(". Received checksum2 = ",zt);
stci_d(numb,(int) sentchecksum2,10);
con_put_str(numb,zt);
con_put_str(".\n",zt);
} /* end if */
} /* end else */
} /* end if sectcurr == (sectnum + 1 & 0xff) */
else
{
if (sectcurr == (sectnum & 0xff))
{
con_put_str("\nReceived Duplicate Sector\n",zt);
sendchar((char) ACK,zt);
} /* end if sectcurr == (sectnum & 0xff) */
else
{ /* didn't receive expected sector number */
errorflag = TRUE;
con_put_str("\nExpecting to receive sector ",zt);
stci_d(numb,(int) sectcurr,10);
con_put_str(numb,zt);
con_put_str(".\nBut received sector ",zt);
stci_d(numb,(int) sectcurr,10);
con_put_str(numb,zt);
con_put_str(" instead.\n",zt);
}
} /* end else */
} /* end if sectcurr + sectcomp == 255 */
else
{
con_put_str("\nSector number, and compliment are not that.\n",zt);
con_put_str("\nSector number sent = ",zt);
stci_d(numb,(int) sectcurr,10);
con_put_str(numb,zt);
con_put_str(" ascii.\n",zt);
con_put_str("\nSector complement sent = ",zt);
stci_d(numb,(int) sectcomp,10);
con_put_str(numb,zt);
con_put_str(" ascii.\n",zt);
errorflag=TRUE;
} /* end else */
} /* end if firstchar == SOH || STX */
else
{
con_put_str("\nOOPS!! We didn't receive SOH or STX!!\n",zt);
}
if (errorflag == TRUE)
{
errors++;
con_put_str("\nError\n",zt);
sendchar((char) NAK,zt);
} /* end if errorflag == true */
/* Read the SOH ^ STX */
zt->st = readchar(&firstchar,zt);
if (zt->st == USER_ABORT)
{
goto xmodem_read_file_exit;
}
} /* end while */
write(fd,bufr,bufptr);
close(fd);
if ((firstchar == EOT) && (errors < ERRORMAX))
{
sendchar((char) ACK,zt);
return(TRUE);
}
goto xmodem_read_file_exit_do;
xmodem_read_file_exit:
write(fd,bufr,bufptr);
close(fd);
xmodem_read_file_exit_do:
return(FALSE);
}
int xmodem_send_file(zt)
struct Z_Term *zt;
{
int sectnum, bytes_to_send, size, attempts, j;
unsigned char sectsend, c;
unsigned int checksum, bufptr;
struct FileLock *lock1, *Lock();
struct FileInfoBlock *infoblock1 = 0;
LONG filesize;
int xfer_current_error_detect_alg;
int i;
unsigned char outchecksum1;
int sync_lost_count;
int xfer_total_blocks;
int timeout_time, fd;
char bufr[BUFSIZE];
char numb[10];
int temp;
xfer_current_error_detect_alg = NULL; /* nullify alg */
timeout_time = 10; /* 10 sec timeout period */
if ((lock1 = Lock(zt->filename,ACCESS_READ)) != NULL) /* get shared lock */
{
infoblock1 = (struct FileInfoBlock *)
AllocMem(sizeof(*infoblock1),MEMF_PUBLIC|MEMF_CLEAR);
Examine(lock1,infoblock1);
filesize = infoblock1->fib_Size;
UnLock(lock1);
FreeMem(infoblock1,sizeof(*infoblock1));
con_put_str("\nSending ",zt);
con_put_str(zt->filename,zt);
con_put_str(".\n",zt);
con_put_str("File is ",zt);
stci_d(numb,(int) filesize,10);
con_put_str(numb,zt);
con_put_str(" bytes long.\n",zt);
con_put_str("Current blocksize is ",zt);
stci_d(numb,zt->xfer_blocksize,10);
con_put_str(numb,zt);
con_put_str(" bytes.\nCurrent error detection algorithm is ",zt);
if (zt->xfer_error_detect_alg == XMODEM_CHECKSUM)
{
con_put_str("checksum",zt);
}
if (zt->xfer_error_detect_alg == XMODEM_CRC16)
{
con_put_str("crc-16",zt);
}
xfer_total_blocks = (filesize / zt->xfer_blocksize);
xfer_total_blocks += 1;
con_put_str(".\nTotal blocks to send is ",zt);
stci_d(numb,xfer_total_blocks,10);
con_put_str(numb,zt);
con_put_str(".",zt);
if ((fd = open(zt->filename, 1)) == NULL)
{
con_put_str("\nError opening send file.\n",zt);
goto xmodem_send_file_exit;
}
con_put_str("\nSending File\n",zt);
} /* end if lock1 != NULL */
else
{
con_put_str("\nCould not open ",zt);
con_put_str(zt->filename,zt);
con_put_str(" for input.\n",zt);
goto xmodem_send_file_exit;
}
attempts = 0;
sectnum = 1;
sectsend = 1;
/* wait for sync char */
sync_lost_count = 1;
do
{
zt->st = readchar(&c,zt);
if (zt->st == USER_ABORT)
{
goto xmodem_send_file_exit;
}
if ((c != NAK) && (c != CCHAR))
{
con_put_str("Not receiving C or NAK.\nAscii ",zt);
temp = (int) c;
stci_d(numb,temp,10);
con_put_str(numb,zt);
con_put_str(" received instead.\n",zt);
}
}
while (((c != NAK) && (c != CCHAR)) && (sync_lost_count++ < ERRORMAX));
if (sync_lost_count >= (ERRORMAX))
{
con_put_str("\nCouldn't sync up.\n",zt);
con_put_str("\nReceiver not sending NAKs or C's.\n",zt);
goto xmodem_send_file_exit;
}
if (c == NAK)
{
xfer_current_error_detect_alg = XMODEM_CHECKSUM;
}
if (c == CCHAR)
{
xfer_current_error_detect_alg = XMODEM_CRC16;
}
if (xfer_current_error_detect_alg == NULL)
{
con_put_str("\nERROR!! Receiver specified unknown error detect alg.\n",zt);
temp = (int) c;
stci_d(numb,temp,10);
con_put_str("\nAscii ",zt);
con_put_str(numb,zt);
con_put_str(" was received.\n",zt);
goto xmodem_send_file_exit;
}
if (xfer_current_error_detect_alg != zt->xfer_error_detect_alg)
{
con_put_str("\nReceiver specified error detection algorithm to be ",zt);
if (xfer_current_error_detect_alg == XMODEM_CHECKSUM)
{
con_put_str("checksum",zt);
}
if (xfer_current_error_detect_alg == XMODEM_CRC16)
{
con_put_str("crc-16",zt);
}
con_put_str(" instead of ",zt);
if (zt->xfer_error_detect_alg == XMODEM_CHECKSUM)
{
con_put_str("checksum.\n",zt);
}
if (zt->xfer_error_detect_alg == XMODEM_CRC16)
{
con_put_str("crc-16.\n",zt);
}
} /* end if current_error_detect_alg != error_detect_alg */
while ((bytes_to_send = read(fd, bufr, BUFSIZE)) && (attempts != RETRYMAX))
{
if (bytes_to_send == EOF)
{
con_put_str("\nError Reading File\n",zt);
goto xmodem_send_file_exit;
}
bufptr = 0;
while ((bytes_to_send > 0) && (attempts != RETRYMAX))
{
attempts = 0;
do
{
if (zt->xfer_blocksize == XMODEM_128_BLOCK)
{
sendchar((char) SOH,zt);
}
if (zt->xfer_blocksize == XMODEM_1024_BLOCK)
{
sendchar((char) STX,zt);
}
sendchar((char) sectsend,zt);
sendchar((char) ~sectsend,zt);
checksum = 0;
size = zt->xfer_blocksize
<= bytes_to_send ? zt->xfer_blocksize : bytes_to_send;
bytes_to_send -= size;
for (j = bufptr; j < (bufptr + zt->xfer_blocksize); j++)
{
if (j < (bufptr + size))
{
sendchar((char) bufr[j],zt);
if (xfer_current_error_detect_alg == XMODEM_CHECKSUM)
{
checksum += bufr[j];
}
if (xfer_current_error_detect_alg == XMODEM_CRC16)
{
checksum = checksum ^ (int) bufr[j] << 8;
for (i = 0;i < 8; ++i)
{
if (checksum & 0x8000)
{
checksum = checksum << 1 ^ 0x1021;
}
else
{
checksum = checksum << 1;
}
} /* end for */
checksum = checksum & 0xffff;
} /* end if */
}
else
{
sendchar((char) NULL,zt);
}
} /* end for */
if (xfer_current_error_detect_alg == XMODEM_CHECKSUM)
{
sendchar((char) checksum & 0xff,zt);
}
if (xfer_current_error_detect_alg == XMODEM_CRC16)
{
outchecksum1 = (checksum >> 8);
sen