home *** CD-ROM | disk | FTP | other *** search
- 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
-
-