home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d114
/
vt100.lha
/
Vt100
/
xmodem.c
< prev
Wrap
C/C++ Source or Header
|
1987-11-22
|
12KB
|
468 lines
/*************************************************************
* vt100 terminal emulator - XMODEM protocol support
*
* v2.7 870825 ACS - Make multi_xfer() non-recursive; on non-ESC in
* readchar() re-do the main window's title.
* 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;
extern struct IntuiText MyTitle;
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);
}
do {
DoIO(Write_Request);
} while(Write_Request->IOSer.io_Error != 0);
if (doxon) Do_XON();
}
/* send a break to the host */
void sendbreak() {
AbortIO(Read_Request);
Wait(1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit);
WaitIO(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;
ULONG class, waitmask;
USHORT code;
Timer.tr_time.tv_secs = ttime;
Timer.tr_time.tv_micro = 0;
SendIO((char *) &Timer.tr_node);
rd = FALSE;
waitmask = ((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) |
( 1L << mywindow->UserPort->mp_SigBit) |
( 1L << Timer_Port->mp_SigBit));
if(reqwinup)
waitmask |= (1L << reqwindow->UserPort->mp_SigBit);
while (rd == FALSE) {
Wait(waitmask);
if (CheckIO(Read_Request)) {
WaitIO(Read_Request);
ch=rs_in[0];
rd = TRUE;
SendIO(Read_Request);
}
if(reqwinup &&
(NewMessage=(struct IntuiMessage *)GetMsg(reqwindow->UserPort))) {
class = NewMessage->Class;
ReplyMsg(NewMessage);
if(class == NEWSIZE)
ReqNewSize(reqwindow->Height, reqwindow->Width);
}
if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
class = NewMessage->Class;
code = NewMessage->Code;
ReplyMsg(NewMessage);
if ((class == RAWKEY) && (code == 69)) {
AbortIO((char *) &Timer);
Wait (1L << Timer_Port->mp_SigBit);
WaitIO((char *) &Timer.tr_node);
InfoMsg1Line("ERROR: User aborted transfer");
timeout = USERABORT;
return('\0');
}
PrintIText(mywindow->RPort, &MyTitle, 0L, 0L);
continue;
}
if (rd == FALSE && CheckIO(&Timer)) {
InfoMsg1Line("ERROR: Timeout waiting for character");
timeout = TIMEOUT;
return('\0');
}
} /* end while */
AbortIO((char *) &Timer);
Wait (1L << Timer_Port->mp_SigBit);
WaitIO((char *) &Timer.tr_node);
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 scrstr2[40];
bytes_xferred = 0L;
ttime = TTIME_SHORT;
if ((fd = creat(file, 0)) < 0)
{
InfoMsg2Line("XMODEM Can't Open File:",file);
return FALSE;
}
else
InfoMsg1Line("XMODEM Receive, <esc> in VT100 window to abort");
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);
InfoMsgNoScroll(scrstr2);
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;
InfoMsgNoScroll(scrstr2);
if (bufptr == BufSize)
{
if (write(fd, bufr, BufSize-128) == EOF)
{
InfoMsg1Line("XMODEM: Error Writing File");
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;
}
InfoMsg1Line("XMODEM: Received Duplicate Sector");
sendchar(ACK);
}
else errorflag = TRUE;
}
}
else errorflag = TRUE;
}
if (errorflag == TRUE)
{
errors++;
InfoMsg1Line("XMODEM: Error");
sendchar(NAK);
}
} /* end while */
if ((firstchar == EOT) && (errors < ERRORMAX))
{
sendchar(ACK);
#ifdef BUGFIXES
/* use firstchar to remember the last char for chopping */
if (bufptr && ((firstchar = bufr[--bufptr]) == 0 || firstchar == 0x1A))
{
while (bufptr && bufr[--bufptr] == firstchar)
;
if (bufptr || bufr[0] != firstchar) /* check for null buffer */
write(fd, bufr, ++bufptr);
}
#else
while (bufptr > 0 && (bufr[--bufptr] == 0x00 ||
bufr[bufptr] == 0x1A)) ;
write(fd, bufr, ++bufptr);
#endif
close(fd);
Do_XON();
ScrollInfoMsg(1);
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 scrstr2[40];
bytes_xferred = 0;
ttime = TTIME_LONG;
if ((fd = open(file, 0)) < 0) {
InfoMsg1Line("XMODEM: Cannot Open Send File");
return FALSE;
}
else
InfoMsg1Line("XMODEM Send, <esc> from VT100 window to abort");
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))
{
InfoMsg1Line("XMODEM: Receiver not sending NAKs");
Do_XON();
return FALSE;
}
while ((bytes_to_send = read(fd, bufr, BufSize)) &&
attempts != RETRYMAX)
{
if (bytes_to_send == EOF)
{
InfoMsg1Line("XMODEM: Error Reading File");
Do_XON();
return FALSE;
}
bufptr = 0;
while (bytes_to_send > 0 && attempts != RETRYMAX)
{
attempts = 0;
sprintf(scrstr2,"Sending block %4d",sectnum);
#ifdef BUGFIXES
size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
bytes_to_send -= size;
#endif
do {
InfoMsgNoScroll(scrstr2);
sendchar(SOH);
sendchar(sectnum);
sendchar(~sectnum);
checksum = 0;
#ifdef BUGFIXES
for (j = bufptr; j < bufptr + size; j++)
{
sendchar(bufr[j]); /* send buffer data */
#else
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]);
#endif
checksum += bufr[j];
}
#ifdef BUGFIXES
if( size < SECSIZ ) /* check if we need to pad */
{
c = bufr[j-1] ? 0 : 0x1A; /* choose correct padding */
j = SECSIZ - size;
checksum += j * c;
while ( j-- )
sendchar(c); /* send padding */
}
#else
else sendchar(0);
#endif
sendchar(checksum);
attempts++;
c = readchar();
if (timeout == USERABORT) {
InfoMsg1Line("XMODEM: ABORTED");
Do_XON();
return FALSE;
}
} while ((c != ACK) && (attempts != RETRYMAX));
bufptr += size;
bytes_xferred += size;
sprintf(scrstr2,"Sent block %4d",sectnum);
InfoMsgNoScroll(scrstr2);
sectnum++;
}
}
close(fd);
if (attempts == RETRYMAX)
{
InfoMsg1Line("XMODEM: No Acknowledgment, ABORTING");
Do_XON();
return FALSE;
}
else
{
attempts = 0;
do {
sendchar(EOT);
attempts++;
} while ((readchar() != ACK) &&
(attempts != RETRYMAX) &&
(timeout != USERABORT)) ;
if (attempts == RETRYMAX)
InfoMsg1Line("XMODEM: No end of file");
}
Do_XON();
ScrollInfoMsg(1);
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, *name_start;
timeout = USERABORT - 1;
for(p=name_start=name; !done && timeout != USERABORT; name_start=++p)
{
if (*(name_start) == '$' && *(name_start+1) == '\0') {
saybye();
return;
}
while(*p == ' ') p++;
while(*p && *p != ',' && *p != ' ') p++;
if (*p == '\0') {
done = TRUE;
multi = 0;
}
else
multi = 1;
*p = '\0';
status = ((*mode)(name_start, multi));
if (status == FALSE) close(fd);
}
server = 0;
multi = 0;
}