home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume15
/
xmodem3.6
/
part04
< prev
next >
Wrap
Text File
|
1988-06-13
|
16KB
|
623 lines
Subject: v15i073: Xmodem release 3.6, Part04/05
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: Steve Grandi <grandi@noao.arizona.edu>
Posting-number: Volume 15, Issue 73
Archive-name: xmodem3.6/part04
: This is a shar archive. Extract with sh, not csh.
echo x - batch.c
sed -e 's/^X//' > batch.c << '!Funky!Stuff!'
X/*
X * Various routines for batch transfer
X */
X
X#include "xmodem.h"
X
X/* make sure filename sent or received in YMODEM batch is canonical. */
X
X/* Incoming: Turn Unix '/' into CP/M ':' and translate to all lower case.
X * Remove trailing dot.
X */
X
Xunixify (name)
Xchar *name;
X {
X char *ptr;
X
X /* change '/' to ':' and convert to lower case */
X for (ptr=name; *ptr; ++ptr)
X {
X if (*ptr == '/')
X *ptr = ':';
X if (isupper (*ptr))
X *ptr |= 040;
X }
X
X /* remove trailing dot if present */
X ptr--;
X if (*ptr == '.')
X *ptr = '\0';
X }
X
X/* make sure filename sent or received in YMODEM batch is canonical. */
X
X/* Outgoing: Turn ':' into '/' (for symmetry!) and turn into all lower case.
X * Remove everything before last '/'. Use "filename" to hold final name.
X */
X
Xchar *
Xcpmify (name)
Xchar *name;
X {
X char *ptr, *slash;
X char *strcpy();
X
X /* find last '/' and copy rest of name */
X
X slash = name;
X for (ptr=name; *ptr; ++ptr)
X if (*ptr == '/')
X slash = ptr + 1;
X strcpy (filename, slash);
X
X /* change ':' to '/' and covert to all lower case */
X
X for (ptr=filename; *ptr; ++ptr)
X {
X if (*ptr == ':')
X *ptr = '/';
X if (isupper (*ptr))
X *ptr |= 040;
X }
X return (filename);
X }
X
X
X/* convert a CP/M file name received in a MODEM7 batch transfer
X * into a unix file name mapping '/' into ':', converting to all
X * upper case and adding dot in proper place.
X * Use "filename" to hold name.
X * Code stolen from D. Thompson's (IRTF) xmodem.c
X */
X
Xchar *
Xcpm_unix (string)
Xunsigned char *string;
X{
X register int i;
X unsigned char *iptr, temp;
X register char *optr;
X
X if (*string == '\0')
X error("Null file name in MODEM7 batch receive", TRUE);
X
X for (iptr=string; (temp = *iptr) ; ) {
X temp &= 0177; /* strips bit 7 */
X if (isupper(temp))
X temp |= 040; /* set bit 5 for lower case */
X if (temp == '/')
X temp=':'; /* map / into : */
X *iptr++ = temp;
X }
X
X /* put in main part of name */
X iptr=string;
X optr=filename;
X for (i=0; i<8; i++) {
X if (*iptr != ' ')
X *optr++ = *iptr++;
X }
X
X /* add dot if necessary */
X if (string[8] != ' ' || string[9] != ' ' || string[10] != ' ')
X *optr++ = '.';
X
X /* put in extension */
X iptr = &string[8];
X for (i=0; i<3; i++) {
X if (*iptr != ' ')
X *optr++ = *iptr++;
X }
X
X *optr++ = '\000';
X return (filename);
X}
X
X/* Send 11 character CP/M filename for MODEM7 batch transmission
X * Returns -1 for a protocol error; 0 if successful
X * NOTE: we tromp a little on the argument string!
X * code stolen from D. Thompson's (IRTF) xmodem.c
X */
X
Xsend_name(name)
Xchar *name;
X{
X register int cksum;
X register char *ptr;
X
X xmdebug("send_name");
X
X /* append cp/m EOF */
X name[NAMSIZ] = CTRLZ;
X name[NAMSIZ+1] = '\000';
X
X /* create checksum */
X ptr = name;
X cksum = 0;
X while (*ptr)
X cksum += *ptr++;
X cksum &= 0x00FF;
X
X /* send filename */
X
X sendbyte(ACK);
X ptr = name;
X sendbyte(*ptr++);
X
X while (*ptr) {
X
X switch (readbyte(15)) {
X
X case ACK: break;
X
X case TIMEOUT: {
X logit("Timeout while sending MODEM7 filename\n");
X sendbyte(BAD_NAME);
X return (-1);
X }
X
X default: {
X logit("Error while sending MODEM7 filename\n");
X sendbyte(BAD_NAME);
X return (-1);
X }
X }
X
X sendbyte (*ptr++);
X }
X
X /* Check checksum returned by other side against my value */
X if (readbyte(16) != cksum) {
X logit("Bad checksum while sending MODEM7 filename\n");
X sendbyte(BAD_NAME);
X return (-1);
X }
X
X sendbyte(ACK);
X return (0);
X}
X
X/* Convert Unix filename to 11 character CP/M file name (8 char name,
X * 3 char extension, dot in between is not included).
X * map ':' into '/'; Use filename to hold name.
X * code stolen from D. Thompson's (IRTF) xmodem.c
X */
X
Xchar *
Xunix_cpm(string)
Xchar *string;
X{
X register char *iptr, *optr, temp;
X int i;
X
X char *rindex();
X char *strcpy();
X
X /* blank 11 character name */
X (void) strcpy (filename," ");
X
X /* strip off any path name */
X if ((iptr = rindex(string,'/')))
X iptr++;
X else
X iptr=string;
X
X /* skip leading '.'s */
X while (*iptr == '.')
X iptr++;
X
X /* copy main part of name */
X optr = filename;
X i = 8;
X while ((i--) && (*iptr) && (*iptr != '.'))
X *optr++ = *iptr++;
X
X /* advance to unix extension, or end of unix name */
X while ((*iptr != '.') && (*iptr))
X iptr++;
X
X /* skip over the '.' */
X while (*iptr == '.')
X iptr++;
X
X /* copy extension */
X optr = &filename[8];
X i=3;
X while ((i--) && (*iptr) && (*iptr != '.'))
X *optr++ = *iptr++;
X
X filename[NAMSIZ] = '\000';
X
X /* Fuss with name */
X for (iptr=filename; (temp = *iptr) ;) {
X temp &= 0177; /* strip bit 7 (parity bit) */
X if (islower(temp))
X temp &= ~040; /* make upper case */
X if (temp == ':')
X temp ='/'; /* map ':' into '/' */
X *iptr++ = temp;
X }
X
X if (DEBUG)
X fprintf (LOGFP, "DEBUG: File %s sent as %s\n", string, filename);
X
X return(filename);
X}
!Funky!Stuff!
echo x - send.c
sed -e 's/^X//' > send.c << '!Funky!Stuff!'
X/** send a file **/
X
X/*
X * Operation of this routine depends on on MDM7BAT and YMDMBAT flags.
X *
X * If "name" is NULL; close out the BATCH send.
X */
X
X#include "xmodem.h"
X
Xsfile(name)
Xchar *name;
X {
X
X char *sectdisp();
X time_t time();
X char *strcpy();
X char *unix_cpm();
X char *cpmify();
X long countnl();
X
X extern unsigned short crctab[1<<B]; /* CRC-16 constant values, see getput.c */
X
X register int bufctr, /* array index for data buffer */
X sectnum; /* packet number for packet header */
X
X register unsigned short checksum; /* checksum/crc */
X
X char blockbuf[BBUFSIZ+6]; /* holds packet as it is constructed */
X
X struct stat filestatbuf; /* file status info */
X
X int fd, /* file descriptor for file being transmitted */
X attempts, /* number of attempts made to transmit a packet */
X nlflag, /* flag that we have to send a LF in next packet */
X sendfin, /* flag that we are sending the last packet */
X closeout, /* flag that we are closing out batch send */
X startup, /* flag that we are starting batch send */
X tmode, /* TRUE for text mode */
X amode, /* TRUE for apple mode */
X filepack, /* TRUE when sending first packet */
X buf1024, /* TRUE when sending 1K packets */
X bbufcnt, /* array index for packet */
X firstchar, /* first character in protocol transaction */
X bufsize, /* packet size (128 or 1024) */
X sendresp; /* response char to sent block received from remote*/
X long sentsect; /* count of 128 byte sectors actually sent */
X long expsect; /* count of 128 byte sectors expected to be sent */
X time_t start; /* starting time of transfer */
X char c;
X
X nbchr = 0; /* clear buffered read char count */
X
X CRCMODE = FALSE; /* Receiver determines use of crc or checksum */
X
X buf1024 = LONGPACK; /* set packet size flag to command line switch */
X
X closeout = FALSE; startup = TRUE; filepack = FALSE; /* indicate state of batch transfer */
X
X tmode = (XMITTYPE == 't') ? TRUE : FALSE; /* set text mode */
X amode = (XMITTYPE == 'a') ? TRUE : FALSE; /* set apple mode */
X
X /* Check on NULL file name */
X if (strcmp(name,"") == 0)
X {
X if (BATCH)
X closeout = TRUE;
X else
X {
X sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X error("NULL file name in send", TRUE);
X }
X }
X
X if (!closeout) /* Are we closing down batch? */
X { /* no; let's send a file */
X logit("----\nXMODEM Send Function\n");
X
X if ((fd = open(name, 0)) < 0)
X {
X sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X error("Can't open file for send", TRUE);
X }
X
X stat(name, &filestatbuf); /* get file status bytes */
X if (tmode) /* count up NLs */
X filestatbuf.st_size += countnl(fd);
X expsect = (filestatbuf.st_size/128) + 1;
X
X if (LOGFLAG)
X {
X fprintf(LOGFP, "File Name: %s\n", name);
X fprintf(LOGFP,"File Size %ldK, %ld Records, %ld Bytes\n",
X (filestatbuf.st_size/1024)+1, expsect, filestatbuf.st_size);
X projtime(expsect, LOGFP);
X }
X }
X else
X {
X logit("----\nXMODEM Send Function\n");
X logit("Closing down Batch Transmission\n");
X }
X
X
X bufsize = buf1024 ? 1024 : 128; /* set sector size */
X if (buf1024 && !closeout)
X logit("1K packet mode chosen\n");
X
X sendfin = nlflag = FALSE;
X attempts = 0;
X
X /* wait for and read startup character */
Xrestart:
X do
X {
X while (((firstchar=readbyte(1)) != NAK) && (firstchar != CRCCHR) && (firstchar != CAN))
X if (++attempts > NAKMAX)
X {
X if (MDM7BAT && startup)
X {
X sendbyte(ACK); sendbyte(EOT);
X }
X error("Remote System Not Responding", TRUE);
X }
X
X if ((firstchar & 0x7f) == CAN)
X if (readbyte(3) == CAN)
X error("Send cancelled at user's request",TRUE);
X
X if (firstchar == CRCCHR)
X {
X CRCMODE = TRUE;
X if (!closeout)
X logit("CRC mode requested\n");
X if (readbyte(1) == KCHR)
X {
X buf1024 = TRUE;
X logit("Receiver invoked 1K packet mode\n");
X }
X }
X }
X while (firstchar != NAK && firstchar != CRCCHR);
X
X if (MDM7BAT && closeout) /* close out MODEM7 batch */
X {
X sendbyte(ACK); sendbyte (EOT);
X flushin(); readbyte(2); /* flush junk */
X return;
X }
X
X if (MDM7BAT && startup) /* send MODEM7 file name */
X {
X if (send_name(unix_cpm(name)) == -1)
X {
X attempts = 0;
X goto restart;
X }
X startup = FALSE;
X attempts = 0;
X goto restart;
X }
X
X sectnum = 1;
X
X if (YMDMBAT) /* Fudge for YMODEM transfer (to send name packet) */
X {
X sectnum = 0;
X bufsize = 128;
X filepack = TRUE;
X }
X
X attempts = sentsect = 0;
X start = time((time_t *) 0);
X
X do /* outer packet building/sending loop; loop till whole file is sent */
X {
X
X if (closeout && YMDMBAT && sectnum == 1) /* close out YMODEM */
X return;
X
X if (YMDMBAT && sectnum == 1) /* get set to send YMODEM data packets */
X {
X bufsize = buf1024 ? 1024 : 128;
X
X do /* establish handshaking again */
X {
X while (((firstchar=readbyte(2)) != CRCCHR) && (firstchar != NAK) && (firstchar != CAN))
X if (++attempts > ERRORMAX)
X error("YMODEM protocol botch, C expected", TRUE);
X if ((firstchar&0x7f) == CAN)
X if (readbyte(3) == CAN)
X error("Send cancelled at User's request", TRUE);
X }
X while ((firstchar != CRCCHR) && (firstchar != NAK));
X
X attempts = 0;
X }
X
X if ((bufsize == 1024) && (attempts > KSWMAX))
X {
X logit("Reducing packet size to 128 due to excessive errors\n");
X bufsize = 128;
X }
X
X if ((bufsize == 1024) && ((expsect - sentsect) < 8))
X {
X logit("Reducing packet size to 128 for tail end of file\n");
X bufsize = 128;
X }
X
X if (sectnum > 0) /* data packet */
X {
X for (bufctr=0; bufctr < bufsize;)
X {
X if (nlflag)
X {
X buff[bufctr++] = LF; /* leftover newline */
X nlflag = FALSE;
X }
X if (getbyte(fd, &c) == EOF)
X {
X sendfin = TRUE; /* this is the last sector */
X if (!bufctr) /* if EOF on sector boundary */
X break; /* avoid sending extra sector */
X buff[bufctr++] = CTRLZ; /* pad with Ctrl-Z for CP/M EOF (even do for binary files) */
X continue;
X }
X
X if (tmode && c == LF) /* text mode & Unix newline? */
X {
X buff[bufctr++] = CR; /* insert carriage return */
X if (bufctr < bufsize)
X buff[bufctr++] = LF; /* insert LF */
X else
X nlflag = TRUE; /* insert on next sector */
X }
X else if (amode && c == LF) /* Apple mode & Unix newline? */
X buff[bufctr++] = CR; /* substitute CR */
X else
X buff[bufctr++] = c; /* copy the char without change */
X }
X
X if (!bufctr) /* if EOF on sector boundary */
X break; /* avoid sending empty sector */
X }
X
X else /* YMODEM filename packet */
X {
X for (bufctr=0; bufctr<bufsize; bufctr++) /* zero packet */
X buff[bufctr]=0;
X if (!closeout)
X {
X strcpy((char *)buff, cpmify(name));
X
X /* put in file name, length, mode */
X {
X register char *p;
X p = (char *)buff + strlen(name) + 1;
X sprintf(p, "%lu %lo %o", filestatbuf.st_size,
X filestatbuf.st_mtime, filestatbuf.st_mode);
X if (DEBUG)
X fprintf(LOGFP, "DEBUG: YMODEM header information: %s\n", p);
X }
X buff[bufsize-2] = (expsect & 0xff); /* put in KMD kludge information */
X buff[bufsize-1] = ((expsect >> 8) & 0xff);
X }
X }
X
X bbufcnt = 0; /* start building block to be sent */
X blockbuf[bbufcnt++] = (bufsize == 1024) ? STX : SOH; /* start of packet char */
X blockbuf[bbufcnt++] = sectnum; /* current sector # */
X blockbuf[bbufcnt++] = ~sectnum; /* and its complement */
X
X checksum = 0; /* initialize checksum */
X for (bufctr=0; bufctr < bufsize; bufctr++)
X {
X blockbuf[bbufcnt++] = buff[bufctr];
X
X if (CRCMODE)
X checksum = (checksum<<B) ^ crctab[(checksum>>(W-B)) ^ buff[bufctr]];
X
X else
X checksum = ((checksum+buff[bufctr]) & 0xff);
X }
X
X if (CRCMODE) /* put in CRC */
X {
X checksum &= 0xffff;
X blockbuf[bbufcnt++] = ((checksum >> 8) & 0xff);
X blockbuf[bbufcnt++] = (checksum & 0xff);
X }
X else /* put in checksum */
X blockbuf[bbufcnt++] = checksum;
X
X attempts = 0;
X
X do /* inner packet loop */
X {
X
X writebuf(blockbuf, bbufcnt); /* write the block */
X flushin(); /* purge anything in input queue */
X
X if (DEBUG)
X fprintf (LOGFP, "DEBUG: %d byte Packet %02xh (%02xh) sent, checksum %02xh %02xh\n",
X bbufcnt, blockbuf[1]&0xff, blockbuf[2]&0xff, blockbuf[bufsize+3]&0xff, blockbuf[bufsize+4]&0xff);
X
X attempts++;
X sendresp = readbyte(10); /* get response from remote */
X
X if (sendresp != ACK)
X {
X if (sendresp == TIMEOUT)
X {
X logitarg("Timeout on sector %s\n",sectdisp(sentsect,bufsize,1));
X }
X else if (sendresp == NAK)
X {
X logitarg("NAK on sector %s\n",sectdisp(sentsect,bufsize,1));
X }
X else
X {
X logitarg("Non-ACK on sector %s\n",sectdisp(sentsect,bufsize,1));
X }
X }
X }
X while((sendresp != ACK) && (attempts < ERRORMAX)); /* close of inner loop */
X
X sectnum++; /* increment to next sector number */
X if (!filepack)
X sentsect += (bufsize == 128) ? 1 : 8;
X filepack = FALSE;
X }
X while (!sendfin && ( attempts < ERRORMAX)); /* end of outer loop */
X
X if (attempts >= ERRORMAX)
X {
X sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X error ("Too many errors in transmission", TRUE);
X }
X
X attempts = 0;
X sendbyte(EOT); /* send 1st EOT to close down transfer */
X
X while ((readbyte(15) != ACK) && (attempts++ < EOTMAX)) /* wait for ACK of EOT */
X {
X if (attempts > 1)
X logitarg("EOT not ACKed, try %d\n", attempts);
X sendbyte(EOT);
X }
X
X if (attempts >= RETRYMAX)
X error("Remote System Not Responding on Completion", TRUE);
X
X close(fd);
X
X logit("Send Complete\n");
X prtime(sentsect, time((time_t *) 0) - start);
X }
!Funky!Stuff!
exit