|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T r
Length: 12131 (0x2f63)
Types: TextFile
Names: »receive.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/xmodem/receive.c«
#include "xmodem.h"
/** receive a file **/
/* returns TRUE if in the midst of a batch transfer */
/* returns FALSE if no more files are coming */
/* This routine is one HUGE do-while loop with far to many indented levels.
* I chose this route to facilitate error processing and to avoid GOTOs.
* Given the troubles I've had keeping the nested IF statements straight,
* I was probably mistaken...
*/
rfile(name)
char *name;
{
char *sectdisp();
char *cpm_unix();
char *strcpy();
time_t time();
int fd, /* file descriptor for created file */
checksum, /* packet checksum */
firstchar, /* first character of a packet */
sectnum, /* number of last received packet (modulo 128) */
sectcurr, /* second byte of packet--should be packet number (mod 128) */
sectcomp, /* third byte of packet--should be complement of sectcurr */
tmode, /* text mode if true, binary mode if false */
errors, /* running count of errors (reset when 1st packet starts */
errorflag, /* set true when packet (or first char of putative packet) is invalid */
fatalerror, /* set within main "read-packet" Do-While when bad error found */
inchecksum, /* incoming checksum or CRC */
expsect, /* expected number of sectors (YMODEM batch) */
bufsize; /* packet size (128 or 1024) */
long recvsectcnt; /* running sector count (128 byte sectors) */
int bufctr; /* number of real chars in read packet */
unsigned char *nameptr; /* ptr in filename for MODEM7 protocol */
time_t start; /* starting time of transfer */
int openflag = FALSE; /* is file open for writing? */
logit("----\nXMODEM File Receive Function\n");
if (CRCMODE)
logit("CRC mode requested\n");
BATCH = FALSE; /* don't know if really are in batch mode ! */
fatalerror = FALSE;
sectnum = errors = recvsectcnt = 0;
bufsize = 128;
tmode = (XMITTYPE == 't') ? TRUE : FALSE;
sleep(1); /* wait a second for other side to get ready */
if (CRCMODE) /* start up transfer */
sendbyte(CRCCHR);
else
sendbyte(NAK);
do /* start of MAIN Do-While loop to read packets */
{
errorflag = FALSE;
do /* start by reading first byte in packet */
{
firstchar = readbyte(6);
}
while ((firstchar != SOH)
&& (firstchar != STX)
&& (firstchar != EOT)
&& (firstchar != ACK || recvsectcnt > 0)
&& (firstchar != TIMEOUT)
&& (firstchar != CAN));
if (firstchar == EOT) /* check for REAL EOT */
{
if (readbyte(1) != TIMEOUT)
{
firstchar = TIMEOUT;
errorflag = TRUE;
logit ("EOT followed by characters; ignored\n");
}
}
if (firstchar == TIMEOUT) /* timeout? */
{
logitarg("Timeout on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
errorflag = TRUE;
}
if (firstchar == CAN) /* bailing out? */
{
if ((readbyte(3) & 0x7f) == CAN)
error("Reception canceled at user's request",TRUE);
else
{
errorflag = TRUE;
logit("Received single CAN character\n");
}
}
if (firstchar == ACK) /* MODEM7 batch? */
{
int i,c;
logit("MODEM7 Batch Protocol\n");
nameptr = buff;
checksum = 0;
for (i=0; i<NAMSIZ; i++)
{
c = readbyte(3);
if (c == CAN)
{
if (readbyte(3) == CAN)
error("Program Canceled by User", TRUE);
else
{
logit("Received single CAN character\n");
errorflag = TRUE;
break;
}
}
if (c == EOT && i == 0)
{
logit("MODEM7 Batch Receive Complete\n");
return (FALSE);
}
if (c == TIMEOUT)
{
logit("Timeout waiting for MODEM7 filename character\n");
errorflag = TRUE;
break;
}
if (c == BAD_NAME)
{
logit("Error during MODEM7 filename transfer\n");
errorflag = TRUE;
break;
}
*nameptr++ = c;
checksum += c;
sendbyte(ACK);
}
if (!errorflag)
{
c = readbyte(3);
if (c == CTRLZ) /* OK; end of string found */
{
sendbyte(checksum + CTRLZ);
if (readbyte(3) == ACK) /* file name found! */
{
xmdebug("MODEM7 file name OK");
*nameptr = '\000';
name = cpm_unix(buff);
BATCH = TRUE;
}
else
{
logit("Checksum error in MODEM7 filename\n");
errorflag = TRUE;
}
}
else
{
logit("Length error in MODEM7 fielname\n");
errorflag = TRUE;
}
}
}
if (firstchar == SOH || firstchar == STX) /* start reading packet */
{
bufsize = (firstchar == SOH) ? 128 : 1024;
if (recvsectcnt == 0) /* 1st data packet, initialize */
{
if (bufsize == 1024)
logit("1K packet mode chosen\n");
start = time((time_t *) 0);
errors = 0;
}
sectcurr = readbyte(3);
sectcomp = readbyte(3);
if ((sectcurr + sectcomp) == 0xff) /* is packet number checksum correct? */
{
if (sectcurr == ((sectnum+1) & 0xff)) /* is packet number correct? */
{
if (DEBUG)
fprintf(LOGFP,"DEBUG: packet %d started\n", sectnum);
/* Read, process and calculate checksum for a buffer of data */
if (readbuf(bufsize, 3, tmode, &checksum, &bufctr) != TIMEOUT)
{
/* verify checksum or CRC */
if (CRCMODE)
{
checksum &= 0xffff;
inchecksum = readbyte(3); /* get 16-bit CRC */
inchecksum = (inchecksum<<8) | readbyte(3);
}
else
inchecksum = readbyte(3); /* get simple 8-bit checksum */
if (inchecksum == checksum) /* good checksum, hence good packet */
{
xmdebug("checksum ok");
errors = 0;
recvsectcnt += (bufsize == 128) ? 1 : 8;
sectnum = sectcurr;
if (!openflag) /* open output file if necessary */
{
openflag = TRUE;
if ((fd = creat(name, CREATMODE)) < 0)
{
sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
error("Can't create file for receive", TRUE);
}
logitarg("File Name: %s\n", name);
}
if (write(fd, (char *) buff, bufctr) < 0)
error("File Write Error", TRUE);
else
sendbyte(ACK); /* ACK the received packet */
}
/* Start handling various errors and special conditions */
else /* bad checksum */
{
logitarg("Checksum Error on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
errorflag = TRUE;
}
}
else /* read timeout */
{
logitarg("Timeout while reading sector %s\n",sectdisp(recvsectcnt,bufsize,1));
errorflag = TRUE;
}
}
else /* sector number is wrong OR Ymodem filename */
{
if (sectcurr == 0 && recvsectcnt == 0) /* Ymodem file-name packet */
{
logit("YMODEM Batch Protocol\n");
/* Read and process a file-name packet */
if (readbuf(bufsize, 3, FALSE, &checksum, &bufctr) != TIMEOUT)
{
/* verify checksum or CRC */
if (CRCMODE)
{
checksum &= 0xffff;
inchecksum = readbyte(3); /* get 16-bit CRC */
inchecksum = (inchecksum<<8) | readbyte(3);
}
else
inchecksum = readbyte(3); /* get simple 8-bit checksum */
if (inchecksum == checksum) /* good checksum, hence good filename */
{
xmdebug("checksum ok");
strcpy(name, (char *)buff);
expsect = ((buff[bufsize-1]<<8) | buff[bufsize-2]);
sendbyte(ACK); /* ACK the packet */
BATCH = TRUE;
if (strlen(name) == 0) /* check for no more files */
{
logit("YMODEM Batch Receive Complete\n");
return (FALSE);
}
unixify(name); /* make filename canonical */
logitarg("YMODEM file name: %s\n", name);
logitarg("YMODEM estimated file length %d sectors\n", expsect);
logitarg("YMODEM header info: %s\n", (char *)buff + strlen(name) + 1);
}
else /* bad filename checksum */
{
logit("checksum error on filename sector\n");
errorflag = TRUE;
}
}
else
{
logit("Timeout while reading filename packet\n");
errorflag = TRUE;
}
}
else if (sectcurr == sectnum) /* duplicate sector? */
{
logitarg("Duplicate sector %s flushed\n", sectdisp(recvsectcnt,bufsize,0));
while(readbyte(3) != TIMEOUT)
;
sendbyte(ACK);
}
else /* no, real phase error */
{
logitarg("Phase Error - Expected packet is %s\n", sectdisp(recvsectcnt,bufsize,1));
errorflag = TRUE;
fatalerror = TRUE;
sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
}
}
}
else /* bad packet number checksum */
{
logitarg("Header Sector Number Error on Sector %s\n", sectdisp(recvsectcnt, bufsize,1));
errorflag = TRUE;
}
} /* END reading packet loop */
if ((errorflag && !fatalerror) || recvsectcnt == 0) /* check on errors or batch transfers */
{
if (errorflag)
errors++;
if (recvsectcnt != 0)
while (readbyte(3) != TIMEOUT) /* wait for line to settle if not beginning */
;
if (CRCMODE && recvsectcnt == 0 && errors == CRCSWMAX)
{
CRCMODE = FALSE;
logit("Sender not accepting CRC request, changing to checksum\n");
sendbyte(NAK);
}
else if (!CRCMODE && recvsectcnt == 0 && errors == CRCSWMAX)
{
CRCMODE = TRUE;
logit("Sender not accepting checksum request, changing to CRC\n");
sendbyte(CRCCHR);
}
else if (CRCMODE && recvsectcnt == 0)
sendbyte(CRCCHR);
else
sendbyte(NAK);
}
}
while ((firstchar != EOT) && (errors < ERRORMAX) && !fatalerror); /* end of MAIN Do-While */
if ((firstchar == EOT) && (errors < ERRORMAX)) /* normal exit? */
{
close(fd);
sendbyte(ACK);
logit("Receive Complete\n");
prtime (recvsectcnt, time((time_t *) 0) - start);
if (BATCH) /* send appropriate return code */
return(TRUE);
else
return(FALSE);
}
else /* no, error exit */
{
if (recvsectcnt != 0)
sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
error("ABORTED -- Too Many Errors", TRUE);
return (FALSE);
}
}