home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d108
/
tek.lha
/
Tek
/
xmodem.c
< prev
Wrap
C/C++ Source or Header
|
1987-10-31
|
10KB
|
407 lines
/*************************************************************
* vt100 terminal emulator - XMODEM protocol support
*
* v2.6 870227 DBW - bug fixes for all the stuff in v2.5
* v2.5 870214 DBW - more additions (see readme file)
* v2.4 861214 DBW - lots of fixes/additions (see readme file)
* v2.3 861101 DBW - minor bug fixes
* v2.2 861012 DBW - more of the same
* v2.1 860915 DBW - new features (see README)
* 860901 ACS - Added Parity and Word Length and support code
* 860823 DBW - Integrated and rewrote lots of code
* 860815 Steve Drew: readchar inproved with real timeouts
* v2.0 860809 DBW - Major rewrite
* v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes
* v1.0 860712 DBW - First version released
*
*************************************************************/
#include "vt100.h"
int enablexon = TRUE;
static unsigned long parity_settings[4] = {
0x96696996,
0x69969669,
0x69969669,
0x96696996 };
/************************************************************
* Send a string (using sendchar below)
************************************************************/
void sendstring(s)
char *s;
{
char c;
while ((c = *s++) != '\000') sendchar(c);
}
/**************************************************************/
/* send char and read char functions for the xmodem function */
/************************************************************/
void sendchar(ch)
int ch;
{
int doxon,i,j,k;
doxon = enablexon;
if (doxon) No_XON();
switch (p_parity) {
case 0: /* no parity */
rs_out[0] = ch & 0xFF;
break;
case 1: /* mark */
rs_out[0] = (ch & 0x7F) | 0x80;
break;
case 2: /* space */
rs_out[0] = ch & 0x7F;
break;
case 3: /* even */
case 4: /* odd */
i = (ch >> 5) & 0x3;
j = ch & 0x1F;
k = ((parity_settings[i] >> j) & 0x1) << 7;
if (p_parity == 3) /* even parity */
rs_out[0] = (ch & 0x7F) | k;
else /* odd parity */
rs_out[0] = (ch & 0x7F) | (k ^ 0x80);
}
DoIO(Write_Request);
if (doxon) Do_XON();
}
/* send a break to the host */
void sendbreak() {
AbortIO(Read_Request);
Read_Request->IOSer.io_Command = SDCMD_BREAK;
DoIO(Read_Request);
Read_Request->IOSer.io_Command = CMD_READ;
SendIO(Read_Request);
}
int readchar()
{
int rd,ch;
Timer.tr_time.tv_secs = ttime;
Timer.tr_time.tv_micro = 0;
SendIO((char *) &Timer.tr_node);
rd = FALSE;
while (rd == FALSE)
{
Wait((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) |
( 1L << mywindow->UserPort->mp_SigBit) |
( 1L << Timer_Port->mp_SigBit));
if (CheckIO(Read_Request))
{
WaitIO(Read_Request);
ch=rs_in[0];
rd = TRUE;
SendIO(Read_Request);
}
if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
if ((NewMessage->Class == RAWKEY) && (NewMessage->Code == 69))
{
AbortIO((char *) &Timer);
Wait (1L << Timer_Port->mp_SigBit);
req("ERROR:","User aborted transfer",0);
timeout = USERABORT;
return('\0');
}
continue;
}
if (rd == FALSE && CheckIO(&Timer)) {
req("ERROR","Timeout waiting for character",0);
timeout = TIMEOUT;
return('\0');
}
} /* end while */
AbortIO((char *) &Timer);
Wait (1L << Timer_Port->mp_SigBit);
timeout = GOODREAD;
return(ch & (p_parity == 0 ? 0xFF : 0x7F));
}
void No_XON() {
/* turn off XON/XOFF processing */
enablexon = FALSE;
Write_Request->io_SerFlags |= SERF_XDISABLED;
Write_Request->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(Write_Request);
Write_Request->IOSer.io_Command = CMD_WRITE;
}
void Do_XON() {
/* turn on XON/XOFF processing */
enablexon = TRUE;
Write_Request->io_SerFlags &= ~SERF_XDISABLED;
Write_Request->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(Write_Request);
Write_Request->IOSer.io_Command = CMD_WRITE;
}
/**************************************/
/* xmodem send and recieve functions */
/************************************/
int XMODEM_Read_File(file)
char *file;
{
int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag;
unsigned int checksum, j, bufptr;
char scrstr[40],scrstr2[40];
bytes_xferred = 0L;
ttime = TTIME_SHORT;
if ((fd = creat(file, 0)) < 0)
{
req("XMODEM Can't Open File:",file,0);
return FALSE;
}
else
strcpy(scrstr,"XMODEM Receive, <esc> to abort");
req(scrstr,"",0);
sectnum = errors = bufptr = 0;
sendchar(NAK);
firstchar = 0;
No_XON();
while (firstchar != EOT && errors != ERRORMAX)
{
errorflag = FALSE;
do { /* get sync char */
firstchar = readchar();
if (timeout != GOODREAD) {
if (timeout == USERABORT || errors++ == ERRORMAX)
Do_XON();
return FALSE;
}
} while (firstchar != SOH && firstchar != EOT);
if (firstchar == SOH)
{
sprintf(scrstr2,"Getting Block %4d...",sectnum);
req(scrstr,scrstr2,0);
sectcurr = readchar();
if (timeout != GOODREAD) { Do_XON(); return FALSE; }
sectcomp = readchar();
if (timeout != GOODREAD) { Do_XON(); return FALSE; }
if ((sectcurr + sectcomp) == 255)
{
if (sectcurr == ((sectnum + 1) & 0xff))
{
checksum = 0;
for (j = bufptr; j < (bufptr + SECSIZ); j++)
{
bufr[j] = readchar();
if (timeout != GOODREAD) { Do_XON(); return FALSE; }
checksum = (checksum + bufr[j]) & 0xff;
}
if (checksum == readchar() && timeout == GOODREAD)
{
errors = 0;
sprintf(scrstr2,"Block %4d verified",sectnum);
sectnum++;
bufptr += SECSIZ;
bytes_xferred += SECSIZ;
req(scrstr,scrstr2,0);
if (bufptr == BufSize)
{
if (write(fd, bufr, BufSize-128) == EOF)
{
req(scrstr,"Error Writing File",0);
Do_XON();
return FALSE;
}
bufptr = 128;
for (j = 0; j < 128; j++)
bufr[j] = bufr[(BufSize-128)+j];
}
sendchar(ACK);
}
else
{
errorflag = TRUE;
if (timeout == USERABORT) { Do_XON(); return FALSE; }
}
}
else
{
/* got a duplicate sector */
if (sectcurr == (sectnum & 0xff))
{
/* wait until we time out for 5secs */
do {
readchar();
} while (timeout == GOODREAD);
if (timeout == USERABORT) {
Do_XON();
return FALSE;
}
req(scrstr,"Received Duplicate Sector",0);
sendchar(ACK);
}
else errorflag = TRUE;
}
}
else errorflag = TRUE;
}
if (errorflag == TRUE)
{
errors++;
req(scrstr,"Error",0);
sendchar(NAK);
}
} /* end while */
if ((firstchar == EOT) && (errors < ERRORMAX))
{
sendchar(ACK);
while (bufptr > 0 && (bufr[--bufptr] == 0x00 ||
bufr[bufptr] == 0x1A)) ;
write(fd, bufr, ++bufptr);
close(fd);
Do_XON();
return TRUE;
}
Do_XON();
return FALSE;
}
int XMODEM_Send_File(file)
char *file;
{
int sectnum, bytes_to_send, size, attempts, c;
unsigned checksum, j, bufptr;
char scrstr[40],scrstr2[40];
bytes_xferred = 0;
ttime = TTIME_LONG;
if ((fd = open(file, 0)) < 0) {
req("XMODEM","Cannot Open Send File",0);
return FALSE;
}
else
strcpy(scrstr,"XMODEM Send, <esc> to abort");
req(scrstr,"",0);
attempts = 0;
sectnum = 1;
No_XON();
/* wait for sync char */
j=1;
while (((c = readchar()) != NAK) && (j++ < ERRORMAX))
if (timeout == USERABORT) { Do_XON(); return(FALSE); }
if (j >= (ERRORMAX))
{
req(scrstr,"Receiver not sending NAKs",0);
Do_XON();
return FALSE;
}
while ((bytes_to_send = read(fd, bufr, BufSize)) &&
attempts != RETRYMAX)
{
if (bytes_to_send == EOF)
{
req(scrstr,"Error Reading File",0);
Do_XON();
return FALSE;
}
bufptr = 0;
while (bytes_to_send > 0 && attempts != RETRYMAX)
{
attempts = 0;
sprintf(scrstr2,"Sending block %4d",sectnum);
do {
req(scrstr,scrstr2,0);
sendchar(SOH);
sendchar(sectnum);
sendchar(~sectnum);
checksum = 0;
size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
bytes_to_send -= size;
for (j = bufptr; j < (bufptr + SECSIZ); j++)
if (j < (bufptr + size)) {
sendchar(bufr[j]);
checksum += bufr[j];
}
else sendchar(0);
sendchar(checksum);
attempts++;
c = readchar();
if (timeout == USERABORT) {
req(scrstr,"ABORTED",0);
Do_XON();
return FALSE;
}
} while ((c != ACK) && (attempts != RETRYMAX));
bufptr += size;
bytes_xferred += size;
sprintf(scrstr2,"Sent block %4d",sectnum);
req(scrstr,scrstr2,0);
sectnum++;
}
}
close(fd);
if (attempts == RETRYMAX)
{
req(scrstr,"No Acknowledgment, ABORTING",0);
Do_XON();
return FALSE;
}
else
{
attempts = 0;
do {
sendchar(EOT);
attempts++;
} while ((readchar() != ACK) &&
(attempts != RETRYMAX) &&
(timeout != USERABORT)) ;
if (attempts == RETRYMAX)
req(scrstr,"NO END OF FILE",0);
}
Do_XON();
return TRUE;
}
/* allow for multi file xfers separated by commas under
kermit and XMODEM */
void multi_xfer(name,mode,do_send)
char *name;
int (*mode)();
int do_send;
{
int done = 0;
int status;
char *p;
if (name[0] == '$' && name[1] == '\0') {
saybye();
return;
}
p = name;
while(*p == ' ') p++;
while(*p && *p != ',' && *p != ' ') p++;
if (*p == '\0') done = TRUE;
else multi = 1;
*p = '\0';
status = ((*mode)(name, multi));
if (status == FALSE) close(fd);
if (!done && timeout != USERABORT) multi_xfer(++p, mode, do_send);
else emit('\n');
server = 0;
multi = 0;
}