v15i074: Xmodem release 3.6, Part05/05
Rich Salz
rsalz at uunet.uu.net
Wed Jun 15 06:26:08 AEST 1988
Submitted-by: Steve Grandi <grandi at noao.arizona.edu>
Posting-number: Volume 15, Issue 74
Archive-name: xmodem3.6/part05
: This is a shar archive. Extract with sh, not csh.
echo x - tip.diffs
sed -e 's/^X//' > tip.diffs << '!Funky!Stuff!'
X
X*** cmdtab.c.ORIG Mon May 5 11:01:59 1986
X--- cmdtab.c Thu Aug 21 10:08:50 1986
X***************
X*** 15,16 ****
X--- 15,17 ----
X extern int cu_take(), cu_put(), dollar(), genbrk(), suspend();
X+ extern int rtfile(), stfile(), rbfile(), sbfile();
X
X***************
X*** 35,36 ****
X--- 36,41 ----
X { '#', NORM, "send break", genbrk },
X+ { '{', NORM, "receive xmodem text file", rtfile },
X+ { '}', NORM, "send xmodem text file", stfile },
X+ { '(', NORM, "receive xmodem binary file", rbfile },
X+ { ')', NORM, "send xmodem binary file", sbfile },
X { 0, 0, 0 }
X
X
X
X*** cmds.c.ORIG Mon May 5 11:01:56 1986
X--- cmds.c Tue Sep 30 10:17:11 1986
X***************
X*** 855,856 ****
X--- 865,1412 ----
X return(0);
X+ }
X+
X+
X+ /* XMODEM stuff; sag sept 1984 - Feb 1985
X+ * Taken from Brian Kantor's (sdccsu3!brian) xmodem version 1.0
X+ * Note that this code will work on version 4.2 ONLY (uses select)
X+ */
X+
X+ #include <sys/stat.h>
X+ #include <sys/time.h>
X+
X+ /* ASCII Constants */
X+ #define SOH 001
X+ #define STX 002
X+ #define ETX 003
X+ #define EOT 004
X+ #define ENQ 005
X+ #define ACK 006
X+ #define LF 012 /* Unix LF/NL */
X+ #define CR 015
X+ #define NAK 025
X+ #define SYN 026
X+ #define CAN 030
X+ #define ESC 033
X+ #define CTRLZ 032 /* CP/M EOF for text (usually!) */
X+
X+ /* XMODEM Constants */
X+ #define TIMEOUT -1
X+ #define ERRORMAX 10 /* maximum errors tolerated */
X+ #define RETRYMAX 10 /* maximum retries to be made */
X+ #define BBUFSIZ 128 /* buffer size -- do not change! */
X+ #define DEBUG 0 /* 1 for debugging output */
X+ #define GETERR -10 /* error code for getbyte routine */
X+
X+ char buff[BBUFSIZ];
X+
X+ int nbchr; /* number of chars read so far for buffered read */
X+
X+ /* Receive a text file */
X+ rtfile(c)
X+ char c;
X+ {
X+ putchar (c);
X+ rfile ('t');
X+ }
X+
X+ /* Receive a binary file */
X+ rbfile(c)
X+ char c;
X+ {
X+ putchar (c);
X+ rfile ('b');
X+ }
X+
X+ /* Send a text file */
X+ stfile(c)
X+ char c;
X+ {
X+ putchar (c);
X+ sfile ('t');
X+ }
X+
X+ /* Send a binary file */
X+ sbfile(c)
X+ char c;
X+ {
X+ putchar (c);
X+ sfile ('b');
X+ }
X+
X+ /* print error message and cleanup for exit */
X+ error(msg)
X+ char *msg;
X+ {
X+ printf("\r\nXMODEM: %s\n", msg);
X+ ioctl (0, TIOCSETC, &tchars);
X+ write (fildes[1], (char *)&ccc, 1);
X+ signal (SIGINT, SIG_DFL);
X+ }
X+
X+ /*
X+ *
X+ * Get a byte from the specified file. Buffer the read so we don't
X+ * have to use a system call for each character.
X+ *
X+ */
X+ getbyte(fildes, ch) /* Buffered disk read */
X+ int fildes;
X+ char *ch;
X+
X+ {
X+ static char buf[BUFSIZ]; /* Remember buffer */
X+ static char *bufp = buf; /* Remember where we are in buffer */
X+
X+ if (nbchr == 0) /* Buffer exausted; read some more */
X+ {
X+ if ((nbchr = read(fildes, buf, BUFSIZ)) < 0)
X+ {
X+ error("File Read Error");
X+ return (GETERR);
X+ }
X+ bufp = buf; /* Set pointer to start of array */
X+ }
X+ if (--nbchr >= 0)
X+ {
X+ *ch = *bufp++;
X+ return(0);
X+ }
X+ else
X+ return(EOF);
X+ }
X+
X+ /** receive a file **/
X+ rfile(mode)
X+ char mode;
X+ {
X+ register int bufctr, checksum;
X+ register int c;
X+ int j, firstchar, sectnum, sectcurr, tmode;
X+ int sectcomp, errors, errorflag, recfin;
X+ int fatalerror, inchecksum;
X+ long recvsectcnt;
X+
X+ int (*f) ();
X+ char *cp, *expand();
X+ time_t start;
X+
X+ if (prompt (" Receive local file name? ", copyname))
X+ return;
X+ cp = expand (copyname);
X+ if ((sfd = creat (cp, 0666)) < 0)
X+ {
X+ printf ("\r\n%s: Cannot creat\r\n", copyname);
X+ return;
X+ }
X+
X+ kill (pid, SIGIOT);
X+ read (repdes[0], (char *)&ccc, 1); /* wait until read process stops */
X+ ioctl (0, TIOCSETC, &defchars); /* set tty modes */
X+ f = signal (SIGINT, intcopy); /* intercept control-c */
X+
X+ start = time(0);
X+ quit = 0;
X+ (void) setjmp(intbuf); /* set control-c catcher */
X+
X+ if (quit)
X+ {
X+ error("Control-C; Reception canceled");
X+ close (sfd);
X+ return;
X+ }
X+
X+ printf("XMODEM: Ready to RECEIVE File %s", cp);
X+ puts("\r\nControl-C to cancel.\n");
X+
X+ recfin = FALSE;
X+ sectnum = errors = 0;
X+ fatalerror = FALSE; /* NO fatal errors */
X+ recvsectcnt = 0; /* number of received sectors */
X+
X+ if (mode == 't')
X+ tmode = TRUE;
X+ else
X+ tmode = FALSE;
X+
X+ sendbyte(NAK); /* Start up the sender's first block */
X+
X+ do
X+ {
X+ errorflag = FALSE;
X+ do
X+ {
X+ firstchar = readbyte(6);
X+ }
X+ while ((firstchar != SOH)
X+ && (firstchar != EOT)
X+ && (firstchar != TIMEOUT)
X+ && ((firstchar & 0x7f) != CAN));
X+
X+ if (firstchar == TIMEOUT)
X+ {
X+ printf("\r\nTimeout on Sector %d\n", sectnum+1);
X+ errorflag = TRUE;
X+ }
X+
X+ if ((firstchar & 0x7f) == CAN)
X+ {
X+ error("Reception canceled at user's request");
X+ close (sfd);
X+ return;
X+ }
X+
X+ if (firstchar == SOH)
X+ {
X+ sectcurr = readbyte(3); /* get sector numbers */
X+ sectcomp = readbyte(3);
X+ if ((sectcurr + sectcomp) == 0xff)
X+ {
X+ if (sectcurr == ((sectnum+1) & 0xff))
X+ {
X+ checksum = 0;
X+ for (j = bufctr = 0; j < BBUFSIZ; j++)
X+ {
X+ buff[bufctr] = c = readbyte(3);
X+ checksum = ((checksum+c) & 0xff);
X+ if (!tmode) /* binary mode */
X+ {
X+ bufctr++;
X+ continue;
X+ }
X+ if (c == CR)
X+ continue; /* skip CR's */
X+ if (c == CTRLZ) /* CP/M EOF char */
X+ {
X+ recfin = TRUE; /* flag EOF */
X+ continue;
X+ }
X+ if (!recfin)
X+ bufctr++;
X+ }
X+ inchecksum = readbyte(3); /* get checksum */
X+ if (checksum == inchecksum) /* good checksum */
X+ {
X+ errors = 0;
X+ recvsectcnt++;
X+ sectnum = sectcurr;
X+ if (DEBUG) printf ("\n");
X+ printf ("\rreceived sector %-4d", recvsectcnt);
X+ if (write(sfd, buff, bufctr) < 0)
X+ {
X+ sendbyte(CAN);
X+ error("File Write Error");
X+ close (sfd);
X+ return;
X+ }
X+ else
X+ sendbyte(ACK);
X+
X+ }
X+ else
X+ {
X+ printf("\r\nChecksum Error on Sector %d\n", sectnum+1);
X+ errorflag = TRUE;
X+ }
X+ }
X+ else
X+ {
X+ if (sectcurr == sectnum)
X+ {
X+ while(readbyte(3) != TIMEOUT)
X+ ;
X+ sendbyte(ACK);
X+ }
X+ else
X+ {
X+ printf("\r\nPhase Error - Received Sector is ");
X+ printf("%d while Expected Sector is %d\n",
X+ sectcurr, ((sectnum+1) & 0xff));
X+ errorflag = TRUE;
X+ fatalerror = TRUE;
X+ sendbyte(CAN);
X+ }
X+ }
X+ }
X+ else
X+ {
X+ printf("\r\nHeader Sector Number Error on Sector %d\n",
X+ sectnum+1);
X+ errorflag = TRUE;
X+ }
X+ }
X+
X+ if (errorflag)
X+ {
X+ errors++;
X+ while (readbyte(3) != TIMEOUT)
X+ ;
X+ sendbyte(NAK);
X+ }
X+ }
X+ while ((firstchar != EOT) && (errors < ERRORMAX) && !fatalerror);
X+
X+ if ((firstchar == EOT) && (errors < ERRORMAX) && !fatalerror)
X+ {
X+ close(sfd);
X+ sendbyte(ACK);
X+ printf("\n\rReceive Complete");
X+ printf("\n\r%ld CP/M Records ", recvsectcnt);
X+ prtime(" transferred in ", time(0)-start);
X+
X+ ioctl (0, TIOCSETC, &tchars); /* reset ttys */
X+ write (fildes[1], (char *)&ccc, 1); /* wakeup tip */
X+ signal (SIGINT, SIG_DFL); /* reset control-c catcher */
X+ }
X+ else
X+ {
X+ sendbyte(CAN);
X+ error("\r\nABORTED -- Too Many Errors");
X+ close (sfd);
X+ return;
X+ }
X+ }
X+
X+ /** send a file **/
X+ sfile(mode)
X+ char mode;
X+ {
X+ register int bufctr, checksum, sectnum;
X+ char blockbuf[134];
X+ int fd, attempts;
X+ int nlflag, sendfin, tmode;
X+ int bbufcnt;
X+ int firstchar;
X+ int getretrn;
X+ char c;
X+ int sendresp; /* response char to sent block */
X+
X+ int (*f) ();
X+ char *cp, *expand();
X+ time_t start;
X+
X+ if (prompt (" Send local file name? ", copyname))
X+ return;
X+ cp = expand (copyname);
X+ if ((fd = open(cp, 0)) < 0)
X+ {
X+ printf("Can't open file for send\n");
X+ return;
X+ }
X+
X+ kill (pid, SIGIOT);
X+ read (repdes[0], (char *)&ccc, 1); /* wait until read process stops */
X+ ioctl (0, TIOCSETC, &defchars); /* setup tty */
X+ f = signal (SIGINT, intcopy); /* prepare to catch control-c */
X+ start = time(0);
X+ quit = 0;
X+ (void) setjmp(intbuf); /* setup control-c catcher */
X+
X+ nbchr = 0; /* clear buffered read char count */
X+
X+ if (quit)
X+ {
X+ sendbyte(CAN);
X+ error("Control-C; Send canceled");
X+ close (fd);
X+ return;
X+ }
X+
X+ printf("XMODEM: File %s Ready to SEND", cp);
X+ prfilestat(cp); /* print file size statistics */
X+ puts("\r\nControl-C to cancel.\n");
X+
X+ if (mode == 't')
X+ tmode = TRUE;
X+ else
X+ tmode = FALSE;
X+
X+ sendfin = nlflag = FALSE;
X+ attempts = 0;
X+
X+ while (((firstchar=readbyte(30)) != NAK) && (firstchar != CAN))
X+ {
X+ if (++attempts > RETRYMAX) {
X+ error("Remote System Not Responding");
X+ close (fd);
X+ return;
X+ }
X+ }
X+
X+ if ((firstchar & 0x7f) == CAN)
X+ {
X+ error("Send cancelled at user's request.");
X+ close (fd);
X+ return;
X+ }
X+
X+ sectnum = 1; /* first sector number */
X+ attempts = 0;
X+
X+ do
X+ {
X+ for (bufctr=0; bufctr < BBUFSIZ;)
X+ {
X+ if (nlflag)
X+ {
X+ buff[bufctr++] = LF; /* leftover newline */
X+ nlflag = FALSE;
X+ }
X+ getretrn = getbyte(fd, &c);
X+ if (getretrn == GETERR)
X+ {
X+ sendbyte(CAN);
X+ error ("Read error on local file");
X+ close (fd);
X+ return;
X+ }
X+ if (getretrn == 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+ if (tmode)
X+ buff[bufctr++] = CTRLZ; /* Control-Z for CP/M EOF */
X+ else
X+ bufctr++;
X+ continue;
X+ }
X+
X+ if (tmode && c == LF) /* text mode & Unix newline? */
X+ {
X+ buff[bufctr++] = CR; /* insert carriage return */
X+ if (bufctr < BBUFSIZ)
X+ buff[bufctr++] = LF; /* insert LF */
X+ else
X+ nlflag = TRUE; /* insert on next sector */
X+ }
X+ else
X+ buff[bufctr++] = c; /* copy the char without change */
X+ }
X+
X+ attempts = 0;
X+
X+ if (!bufctr) /* if EOF on sector boundary */
X+ break; /* avoid sending empty sector */
X+
X+ do
X+ {
X+ bbufcnt = 0; /* start building block to be sent */
X+ blockbuf[bbufcnt++] = SOH; /* start of packet char */
X+ blockbuf[bbufcnt++] = sectnum; /* current sector # */
X+ blockbuf[bbufcnt++] = -sectnum-1; /* and its complement */
X+
X+ checksum = 0; /* init checksum */
X+ for (bufctr=0; bufctr < BBUFSIZ; bufctr++)
X+ {
X+ blockbuf[bbufcnt++] = buff[bufctr];
X+ checksum = ((checksum+buff[bufctr]) & 0xff);
X+ }
X+
X+ blockbuf[bbufcnt++] = checksum;
X+ write(FD, blockbuf, 132); /* write the block */
X+ ioctl(FD,TIOCFLUSH,0);
X+
X+ attempts++;
X+ sendresp = readbyte(10); /* get response */
X+ if (sendresp != ACK)
X+ {
X+ printf("\r\nNon-ACK Received on Sector %d\n",sectnum);
X+ if (sendresp == TIMEOUT)
X+ printf("\r\nThis Non-ACK was a TIMEOUT\n");
X+ }
X+ }
X+ while((sendresp != ACK) && (attempts < RETRYMAX));
X+
X+ sectnum++; /* increment to next sector number */
X+ if (DEBUG) printf ("\n");
X+ printf ("\rsent sector %-4d", sectnum-1);
X+ }
X+ while (!sendfin && (attempts < RETRYMAX));
X+
X+ if (attempts >= RETRYMAX)
X+ {
X+ error("Remote System Not Responding");
X+ close (fd);
X+ return;
X+ }
X+
X+ attempts = 0;
X+ sendbyte(EOT); /* send 1st EOT */
X+
X+ while ((readbyte(15) != ACK) && (attempts++ < RETRYMAX))
X+ sendbyte(EOT);
X+
X+ if (attempts >= RETRYMAX)
X+ error("Remote System Not Responding on Completion");
X+
X+ close(fd);
X+ printf("\r\nSend Complete\r\n");
X+ prtime("Data transferred in ", time(0)-start);
X+
X+ ioctl (0, TIOCSETC, &tchars); /* restore tty */
X+ write (fildes[1], (char *)&ccc, 1); /* wakeup tip */
X+ signal (SIGINT, SIG_DFL); /* reset control-c catcher */
X+ sleep(5); /* give other side time to return to terminal mode */
X+
X+ }
X+
X+ /* print file size status information */
X+ prfilestat(name)
X+ char *name;
X+ {
X+ struct stat filestatbuf; /* file status info */
X+
X+ stat(name, &filestatbuf); /* get file status bytes */
X+ printf("\r\nEstimated File Size %ldK, %ld Records, %ld Bytes",
X+ (filestatbuf.st_size/1024)+1, (filestatbuf.st_size/128)+1,
X+ filestatbuf.st_size);
X+ return;
X+ }
X+
X+ /* get a byte from data stream -- timeout if "seconds" elapses */
X+ int readbyte(seconds)
X+ int seconds;
X+ {
X+ int i, readfd;
X+ char c;
X+ struct timeval tmout;
X+
X+ tmout.tv_sec = seconds;
X+ tmout.tv_usec = 0;
X+
X+ readfd = 1 << FD;
X+
X+ if ((i=select(FD+1, &readfd, 0, 0, &tmout)) == 0)
X+ {
X+ return(TIMEOUT);
X+ }
X+
X+ read(FD, &c, 1);
X+
X+ return(c & 0xff); /* return the char */
X+ }
X+
X+ /* send a byte to data stream */
X+ sendbyte(data)
X+ char data;
X+ {
X+ write(FD, &data, 1); /* write the byte */
X+ ioctl(FD,TIOCFLUSH,0); /* flush so it really happens now! */
X+ return;
X+ }
X+
X+ /*
X+ * "nap" for specified time
X+ */
X+ nap (milliseconds)
X+ int milliseconds;
X+ {
X+ struct timeval timeout;
X+
X+ if (milliseconds == 0)
X+ return;
X+ timeout.tv_sec = 0;
X+ timeout.tv_usec = milliseconds * 1000;
X+
X+ (void) select(1, 0, 0, 0, &timeout);
X }
!Funky!Stuff!
exit
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list