home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume23
/
xmodem3.9
/
part02
/
send.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-08
|
12KB
|
430 lines
/** send a file **/
/*
* Operation of this routine depends on on MDM7BAT and YMDMBAT flags.
*
* If "name" is NULL; close out the BATCH send.
*/
#include "xmodem.h"
sfile(name)
char *name;
{
char *sectdisp();
time_t time();
char *strcpy();
char *unix_cpm();
char *cpmify();
long countnl();
extern unsigned short crctab[1<<B]; /* CRC-16 constant values, see getput.c */
register int bufctr, /* array index for data buffer */
sectnum; /* packet number for packet header */
register unsigned short checksum; /* checksum/crc */
char blockbuf[BBUFSIZ+6]; /* holds packet as it is constructed */
struct stat filestatbuf; /* file status info */
int fd, /* file descriptor for file being transmitted */
attempts, /* number of attempts made to transmit a packet */
nlflag, /* flag that we have to send a LF in next packet */
sendfin, /* flag that we are sending the last packet */
closeout, /* flag that we are closing out batch send */
startup, /* flag that we are starting batch send */
tmode, /* TRUE for text mode */
amode, /* TRUE for apple mode */
filepack, /* TRUE when sending first packet */
buf1024, /* TRUE when sending 1K packets */
bbufcnt, /* array index for packet */
firstchar, /* first character in protocol transaction */
bufsize, /* packet size (128 or 1024) */
sendresp; /* response char to sent block received from remote*/
long sentsect; /* count of 128 byte sectors actually sent */
long expsect; /* count of 128 byte sectors expected to be sent */
time_t start; /* starting time of transfer */
char c;
nbchr = 0; /* clear buffered read char count */
CRCMODE = FALSE; /* Receiver determines use of crc or checksum */
YMODEMG = FALSE; /* Receiver determines use YMODEM-G */
buf1024 = LONGPACK; /* set packet size flag to command line switch */
closeout = FALSE; startup = TRUE; filepack = FALSE; /* indicate state of batch transfer */
tmode = (XMITTYPE == 't') ? TRUE : FALSE; /* set text mode */
amode = (XMITTYPE == 'a') ? TRUE : FALSE; /* set apple mode */
/* Check on NULL file name */
if (strcmp(name,"") == 0)
{
if (BATCH)
closeout = TRUE;
else
{
sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
error("NULL file name in send", TRUE);
}
}
if (!closeout) /* Are we closing down batch? */
{ /* no; let's send a file */
logit("----\nXMODEM Send Function\n");
tlogit("----\nXMODEM Send Function\n");
if ((fd = open(name, 0)) < 0)
{
sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
error("Can't open file for send", TRUE);
}
stat(name, &filestatbuf); /* get file status bytes */
if (tmode) /* count up NLs */
filestatbuf.st_size += countnl(fd);
expsect = (filestatbuf.st_size/128) + 1;
if (LOGFLAG)
{
fprintf(LOGFP, "File Name: %s\n", name);
fprintf(LOGFP,"File Size %ldK, %ld Records, %ld Bytes\n",
(filestatbuf.st_size/1024)+1, expsect, filestatbuf.st_size);
projtime(expsect, LOGFP);
}
if (TIPFLAG)
{
fprintf(stderr, "File Name: %s\n", name);
fprintf(stderr,"File Size %ldK, %ld Records, %ld Bytes\n",
(filestatbuf.st_size/1024)+1, expsect, filestatbuf.st_size);
projtime(expsect, stderr);
}
}
else
{
logit("----\nXMODEM Send Function\n");
logit("Closing down Batch Transmission\n");
tlogit("Closing down Batch Transmission\n");
}
bufsize = buf1024 ? 1024 : 128; /* set sector size */
if (buf1024 && !closeout)
{
logit("1K packet mode chosen on command line\n");
tlogit("1K packet mode chosen on command line\n");
}
sendfin = nlflag = FALSE;
attempts = 0;
/* wait for and read startup character */
restart:
do
{
while (((firstchar=readbyte(1)) != NAK) && (firstchar != CRCCHR) && (firstchar != GCHR) && (firstchar != CAN))
if (++attempts > NAKMAX)
{
if (MDM7BAT && startup)
{
sendbyte(ACK); sendbyte(EOT);
}
error("Remote System Not Responding", TRUE);
}
if ((firstchar & 0x7f) == CAN)
if (readbyte(3) == CAN)
error("Send Canceled by CAN-CAN",TRUE);
if (firstchar == GCHR)
{
CRCMODE = TRUE;
YMODEMG = TRUE;
CANCAN = TRUE;
if (!closeout)
{
logit("Receiver invoked YMODEM-G and CRC modes\n");
tlogit("Receiver invoked YMODEM-G and CRC modes\n");
}
}
if (firstchar == CRCCHR)
{
CRCMODE = TRUE;
if (!closeout)
{
logit("Receiver invoked CRC mode\n");
tlogit("Receiver invoked CRC mode\n");
}
if (readbyte(1) == KCHR)
{
buf1024 = TRUE;
logit("Receiver invoked 1K packet mode\n");
tlogit("Receiver invoked 1K packet mode\n");
}
}
}
while (firstchar != NAK && firstchar != CRCCHR && firstchar != GCHR);
if (MDM7BAT && closeout) /* close out MODEM7 batch */
{
sendbyte(ACK); sendbyte (EOT);
flushin(); readbyte(2); /* flush junk */
return;
}
if (MDM7BAT && startup) /* send MODEM7 file name */
{
if (send_name(unix_cpm(name)) == -1)
{
attempts = 0;
goto restart;
}
startup = FALSE;
attempts = 0;
goto restart;
}
sectnum = 1;
if (YMDMBAT) /* Fudge for YMODEM transfer (to send name packet) */
{
sectnum = 0;
bufsize = 128;
filepack = TRUE;
}
attempts = sentsect = 0;
start = time((time_t *) 0);
do /* outer packet building/sending loop; loop till whole file is sent */
{
if (closeout && YMDMBAT && sectnum == 1) /* close out YMODEM */
return;
if (YMDMBAT && sectnum == 1) /* get set to send YMODEM data packets */
{
bufsize = buf1024 ? 1024 : 128;
do /* establish handshaking again */
{
while (((firstchar=readbyte(2)) != CRCCHR) && (firstchar != GCHR) && (firstchar != NAK) && (firstchar != CAN))
if (++attempts > ERRORMAX)
error("YMODEM protocol botch, C or G expected", TRUE);
if ((firstchar&0x7f) == CAN)
if (readbyte(3) == CAN)
error("Send Canceled by CAN-CAN", TRUE);
}
while ((firstchar != CRCCHR) && (firstchar != GCHR) && (firstchar != NAK));
attempts = 0;
}
if ((bufsize == 1024) && (attempts > KSWMAX))
{
logit("Reducing packet size to 128 due to excessive errors\n");
tlogit("Reducing packet size to 128 due to excessive errors\n");
bufsize = 128;
}
if ((bufsize == 1024) && ((expsect - sentsect) < 8))
{
logit("Reducing packet size to 128 for tail end of file\n");
tlogit("Reducing packet size to 128 for tail end of file\n");
bufsize = 128;
}
if (sectnum > 0) /* data packet */
{
for (bufctr=0; bufctr < bufsize;)
{
if (nlflag)
{
buff[bufctr++] = LF; /* leftover newline */
nlflag = FALSE;
}
if (getbyte(fd, &c) == EOF)
{
sendfin = TRUE; /* this is the last sector */
if (!bufctr) /* if EOF on sector boundary */
break; /* avoid sending extra sector */
buff[bufctr++] = CTRLZ; /* pad with Ctrl-Z for CP/M EOF (even do for binary files) */
continue;
}
if (tmode && c == LF) /* text mode & Unix newline? */
{
buff[bufctr++] = CR; /* insert carriage return */
if (bufctr < bufsize)
buff[bufctr++] = LF; /* insert LF */
else
nlflag = TRUE; /* insert on next sector */
}
else if (amode && c == LF) /* Apple mode & Unix newline? */
buff[bufctr++] = CR; /* substitute CR */
else
buff[bufctr++] = c; /* copy the char without change */
}
if (!bufctr) /* if EOF on sector boundary */
break; /* avoid sending empty sector */
}
else /* YMODEM filename packet */
{
for (bufctr=0; bufctr<1024; bufctr++) /* zero packet */
buff[bufctr]=0;
if (!closeout)
{
strcpy((char *)buff, cpmify(name));
/* put in file name, length, mode, */
/* dummy SN, files, bytes remaining and file type */
{
register char *p;
p = (char *)buff + strlen(buff) + 1;
sprintf(p, "%lu %lo %o 0 %d %ld 0", filestatbuf.st_size,
filestatbuf.st_mtime, filestatbuf.st_mode,
yfilesleft, ytotleft);
if (DEBUG)
fprintf(LOGFP, "DEBUG: YMODEM header information: %s %s\n", buff, p);
}
if (buff[125]) /* need to have long packet? */
{
bufsize = 1024;
if (DEBUG)
fprintf(LOGFP, "DEBUG: YMODEM header sent in 1024 byte packet\n");
}
buff[bufsize-2] = (expsect & 0xff); /* put in KMD kludge information */
buff[bufsize-1] = ((expsect >> 8) & 0xff);
/* update totals */
ytotleft -= filestatbuf.st_size;
if (--yfilesleft <= 0)
ytotleft = 0;
if (ytotleft < 0)
ytotleft = 0;
}
}
bbufcnt = 0; /* start building block to be sent */
blockbuf[bbufcnt++] = (bufsize == 1024) ? STX : SOH; /* start of packet char */
blockbuf[bbufcnt++] = sectnum; /* current sector # */
blockbuf[bbufcnt++] = ~sectnum; /* and its complement */
checksum = 0; /* initialize checksum */
for (bufctr=0; bufctr < bufsize; bufctr++)
{
blockbuf[bbufcnt++] = buff[bufctr];
if (CRCMODE)
checksum = (checksum<<B) ^ crctab[(checksum>>(W-B)) ^ buff[bufctr]];
else
checksum = ((checksum+buff[bufctr]) & 0xff);
}
if (CRCMODE) /* put in CRC */
{
checksum &= 0xffff;
blockbuf[bbufcnt++] = ((checksum >> 8) & 0xff);
blockbuf[bbufcnt++] = (checksum & 0xff);
}
else /* put in checksum */
blockbuf[bbufcnt++] = checksum;
attempts = 0;
do /* inner packet loop */
{
writebuf(blockbuf, bbufcnt); /* write the block */
if (!YMODEMG)
flushin(); /* purge anything in input queue */
if (DEBUG)
fprintf (LOGFP, "DEBUG: %d byte Packet %02xh (%02xh) sent, checksum %02xh %02xh\n",
bbufcnt, blockbuf[1]&0xff, blockbuf[2]&0xff, blockbuf[bufsize+3]&0xff, blockbuf[bufsize+4]&0xff);
attempts++;
sendresp = (YMODEMG) ? ACK : readbyte(10); /* get response from remote (or fake it for YMODEM-G) */
if (sendresp != ACK)
{
if (sendresp == TIMEOUT)
{
logitarg("Timeout on sector %s\n",sectdisp(sentsect,bufsize,1));
tlogitarg("Timeout on sector %s\n",sectdisp(sentsect,bufsize,1));
}
if (sendresp == CAN)
{
if (CANCAN)
{
if (readbyte(3) == CAN)
error("Send Canceled by CAN-CAN",TRUE);
}
else
{
logitarg("ignored CAN on sector %s\n",sectdisp(sentsect,bufsize,1));
tlogitarg("ignored CAN on sector %s\n",sectdisp(sentsect,bufsize,1));
}
}
else if (sendresp == NAK)
{
logitarg("NAK on sector %s\n",sectdisp(sentsect,bufsize,1));
tlogitarg("NAK on sector %s\n",sectdisp(sentsect,bufsize,1));
}
else
{
logitarg("Non-ACK on sector %s\n",sectdisp(sentsect,bufsize,1));
tlogitarg("Non-ACK on sector %s\n",sectdisp(sentsect,bufsize,1));
}
}
}
while((sendresp != ACK) && (attempts < ERRORMAX)); /* close of inner loop */
sectnum++; /* increment to next sector number */
if (!filepack)
sentsect += (bufsize == 128) ? 1 : 8;
filepack = FALSE;
if (TIPFLAG && sentsect % 32 == 0)
tlogitarg("Sector %s sent\n", sectdisp(sentsect,bufsize,0));
}
while (!sendfin && ( attempts < ERRORMAX)); /* end of outer loop */
if (attempts >= ERRORMAX)
{
sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
error ("Too many errors in transmission", TRUE);
}
sendbyte(EOT); /* send 1st EOT to close down transfer */
attempts = 0;
while ((readbyte(15) != ACK) && (attempts++ < EOTMAX)) /* wait for ACK of EOT */
{
if (attempts > 1)
{
logitarg("EOT not ACKed, try %d\n", attempts);
tlogitarg("EOT not ACKed, try %d\n", attempts);
}
sendbyte(EOT);
}
if (attempts >= RETRYMAX)
error("Remote System Not Responding on Completion", TRUE);
close(fd);
logit("Send Complete\n");
tlogit("Send Complete\n");
if (LOGFLAG)
prtime(sentsect, time((time_t *) 0) - start, LOGFP);
if (TIPFLAG)
prtime(sentsect, time((time_t *) 0) - start, stderr);
}