v23i077: Xmodem file transfer program, revision3.9, Part01/03

Rich Salz rsalz at bbn.com
Thu Dec 6 04:33:54 AEST 1990


Submitted-by: Steve Grandi <grandi at noao.edu>
Posting-number: Volume 23, Issue 77
Archive-name: xmodem3.9/part01

The xmodem program implements the Christensen (XMODEM) file transfer
protocol for moving files between 4.2/4.3BSD Unix systems (and successors,
including Suns) and microcomputers.  The XMODEM/CRC protocol, the MODEM7
batch protocol, the XMODEM-1K block protocol, the YMODEM batch protocol
and the YMODEM-G streaming protocol are all supported by xmodem.  The
ZMODEM protocol is not supported.

This is version 3.9 (circa 11/90) of the xmodem program which incorporates
a few bugfixes (one important!) and some enhancements: 1) status messages
when running xmodem through Sun's tip program ("p" flag); 2) delayed
startup (via the "w" flag); 3) ability to turn off EOT verification (via
"e" flag); 4) ability to allow CAN-CAN abort in the midst of a file
transfer (via "n"  flag) and 5) YMODEM-G support (via the "g" flag).  See
update.doc for details. 

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# Contents:  README Makefile receive.c xmodem.c
# Wrapped by rsalz at litchi.bbn.com on Wed Dec  5 12:31:56 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 1 (of 3)."'
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
  echo shar: Extracting \"'README'\" \(21493 characters\)
  sed "s/^X//" >'README' <<'END_OF_FILE'
XThis is version 3.9 (circa 11/90) of the xmodem program which incorporates
Xa few bugfixes (one important!) and some enhancements: 1) status messages
Xwhen running xmodem through Sun's tip program ("p" flag); 2) delayed
Xstartup (via the "w" flag); 3) ability to turn off EOT verification (via
X"e" flag); 4) ability to allow CAN-CAN abort in the midst of a file
Xtransfer (via "n"  flag) and 5) YMODEM-G support (via the "g" flag).  See
Xupdate.doc for details. 
X
X--------------------------------------------------------------------------------
X
XThis is version 3.8 (circa 11/88) of the xmodem program which incorporates
Xminor enhancements over version 3.7 which incoporates minor enhancements
Xover version 3.6.  See update.doc. 
X
X--------------------------------------------------------------------------------
X
XThis is version 3.6 (finished 4/88) of the xmodem program which includes a
Xfew bugfixes and some enhancements (requested by Macintosh users)
Xstimulated by the xmodem release through comp.sources.unix.  See the file
Xupdate.doc for details. 
X
X--------------------------------------------------------------------------------
X
XThis is version 3.4 (finished 10/87) of the xmodem program, a full-featured
XXMODEM implementation for 4.3BSD.  Since the previous release (version
X3.2, see volume 7 of the archives), substantial improvements have been
Xmade. See the file update.doc for details.  Also, some attempt has been
Xmade to support SysV Unix systems; see below.
X
XAs far as I am concerned, this program has reached the end of its evolution.
XNewer protocols (such as ZMODEM) will not be incorporated into xmodem.  Check
Xout Chuck Forsberg's rz/sz programs if you are interested in ZMODEM.
X
X--------------------------------------------------------------------------------
X
XThe xmodem program implements the Christensen (XMODEM) file transfer
Xprotocol for moving files between 4.2/4.3BSD Unix systems and microcomputers.
XThe XMODEM/CRC protocol, the MODEM7 batch protocol, the XMODEM-1K
Xblock protocol and the YMODEM batch protocol are all supported by xmodem.
XFor details of the protocols, see the document edited by Chuck Forsberg titled
XXMODEM/YMODEM Protocol Reference (the latest version is dated 6-18-88).
X
XThis program runs on 4.2/4.3BSD systems ONLY.  It has been tested on VAXes
Xand Suns against the MEX-PC program from Niteowl Software and the ZCOMM and
XDSZ programs from Omen Technology.
X
XI have tried to keep the 4.2isms (select system call, 4.2BSD/v7 tty structures,
Xgettimeofday system call, etc.) confined to the source file getput.c; but I 
Xmake no guarantees.  Also, I have made no attempt to keep variable names 
Xunder 7 characters.  A version of getput.c that MAY work on Sys V Unix
Xsystems is included.
X
X--------------------------------------------------------------------------------
X
XThanks to Emmet Gray (ihnp4!uiucuxc!fthood!egray) and John Rupley 
X(arizona!rupley!root) for the following notes about converting xmodem to Sys V.
XSince I don't have a Sys V system to test a Sys V version, I won't even try.
X
X1) Change the includes in xmodem.h from <sys/time.h> to <time.h>
X   and from <sgtty.h> to <termio.h>
X
X2) Convert the occurrences of rindex to strrchr in batch.c
X
X3) Substitute getput.sysv.c for getput.c
X
XA further "gotcha" regarding Sys V is contained in the following message :
X
XFrom: Bill Stubblebine <hplsdls!was at hp-lsd.UUCP>
XDate: Sat, 25 Jun 88 13:36:20 mdt
XTo: grandi at noao.arizona.edu
XSubject: xmodem3.6 bug, fix and THANKS!!
X
X						1:30 PM MDT
X						June 25, 1988
X
XFirst, thanks for posting a really useful program, xmodem 3.6.
X
XI installed the xmodem program on an HP 9000 Series 350 workstation,
Xrunning HP-UX version 6.01 (AT&T System V compatible) to talk to my
XCP/M system at home.  MODEM7 batch is particularly useful.
X
XI'd like to report a bug I found and the fix I developed in the source
Xfile getput.sysv.c so that you can include it in future releases.
X
XI've reproduced the relevant portion of getput.sysv.c, modified to fix
Xthe bug, at the end of this file.  See the routine getspeed() starting
Xat line 382.  Getspeed() derives the serial port speed from the
Xc_cflag ioctl parameter, for use in estimating transmission times.
X
XI suspected something was wrong when xmodem kept reporting 1200 baud
Xmodem connections as 1800 baud in the log file, but the transfers
Xstill worked OK at 1200 baud.  However, I also have a Courier HST 9600
Xbaud modem at home, and when I tried 9600 baud xmodem transfers,
Xxmodem would core dump on the UNIX host.
X
XOn line 386 of getput.sysv.c, in the procedure getspeed(), an array is
Xdeclared containing numerical constants representing the various baud
Xrates supported by the host terminal interface.  The appropriate baud
Xrate constant is selected by the statements in lines 392-394, which
Xmask the c_cflag baud rate bitfield to index into the speedtbl[]
Xarray.
X
XThere are two problems here.  The first problem is that speedtbl[] is
Xmissing some valid baud rate entries, as the modified declaration
Xshows.  I got the entries for the modified declaration from the
Xtermio(7) manpage in my System V user's manual.  The missing entries
Xthrow off the indexing arithmetic.  Notice, for example, that the
Xmissing entry 900 was responsible for mapping the c_cflag bits for
X1200 baud to the 1800 baud constant.
X
XOriginal declaration:
X  static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
X  1200, 1800, 2400, 4800, 9600, 19200, 0};
X
XModified declaration:
X  static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
X  900, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 19200, 38400, 0};
X  ^^^                    ^^^^        ^^^^        ^^^^^  ^^^^^
X
XThe second problem didn't show up until I used 9600 baud.  The c_cflag
Xbitfield value for 9600 baud is 16 decimal (020 octal).  The masking
Xconstant in lines 392-394 was originally 017 octal, which masked the
X9600 baud bitfield to 0, indexing to the speedtbl[] value of 0.  Speed
Xcalculations using a baudrate of 0 caused floating point exceptions
Xleading to the host core dumps at 9600 baud.
X
XI changed the mask value from 017 octal to 037 octal (which is
Xactually the size of the c_cflag baudrate field), and changed the
Xlimit test in line 392 from 14 to 18, the new correct number of
Xelements in the speedtbl[] array.
X
XI'm not familiar with 4.2BSD, but I noticed that getput.c, the 4.2BSD
Xversion of the I/O routines, contains virtually the same code for
Xdetermining the baudrate as that in getput.sysv.c.  It may be OK for
X4.2BSD, but definitely not for System V.
X
XThe modified code now works great at all baud rates!  Thanks again for
Xposting the program.
X
X                                Bill Stubblebine
X                                Hewlett-Packard Logic Systems Div.
X				8245 N. Union Blvd.
X                                Colorado Springs, Co. 80918
X				ARPA: was%hp-lsd at hplabs.hp.com
X				UUCP: {hplabs,hpfcla}!{hpldola,hp-lsd}!was
X
X--------------------------------------------------------------------------------
X
XA common request to me concerns running xmodem through tip in order to do
XXMODEM or YMODEM transfers.  I have discovered that SunOS has a nice
Xfeature in tip (accessed through ~C) that connects a named program to a
Xremote machine.  It turns out that 4.3BSD tip has a similar (but
Xundocumented) feature, but far less convenient: SunOS tip connects file
Xdescriptor 0 of the program to the remote line input and file descriptor 1
Xto remote line output while 4.3BSD connects up file descriptors 3 and 4! 
X
XIf you would like to use xmodem through 4.3BSD tip, the following message
Xshould be of interest (note that the patches given below are against an old
Xversion of the source):
X
XTo: grandi at noao.edu (Steve Grandi CCS)
XSubject: Re: xmodem 
XDate: Tue, 02 Jan 90 12:34:58 -0500
XFrom: Benson I. Margulies <benson at odi.com>
X
X
X    Yes, I would like to receive the changes!
X
X    Steve, grandi at noao.edu
X
XOK, here are the diffs. I've tested them in receive mode,
Xbut I haven't been able to verify that they work for sending.
XThe reason why is a long sob story.
X
XIt would be good to do two additional things:
X
X1) add some \r's to the messages printed.
X2) when in tip mode, print more messages on stdout
Xto report progress, like a . every 100 blocks.
X
XRCS file: RCS/xmodem.c,v
Xretrieving revision 1.1
Xretrieving revision 1.2
Xdiff -c -r1.1 -r1.2
X*** /tmp/,RCSt1a02154	Tue Jan  2 12:33:12 1990
X--- /tmp/,RCSt2a02154	Tue Jan  2 12:33:12 1990
X***************
X*** 52,57 ****
X--- 52,60 ----
X  	MDM7BAT = FALSE;	/* no MODEM7 batch mode */
X  	YMDMBAT = FALSE;	/* no YMODEM batch mode */
X  	TOOBUSY = FALSE;	/* not too busy for sleeping in packet read */
X+ 	INFD = 0;
X+ 	OUTFD = 1;
X+ 	FDS_DISTINCT = 0;
X  
X  	fprintf(stderr, "XMODEM Version %d.%d", VERSION/10, VERSION%10);
X  	fprintf(stderr, " -- UNIX-Microcomputer Remote File Transfer Facility\n");
X***************
X*** 101,106 ****
X--- 104,115 ----
X  		case 's' : SENDFLAG = TRUE;  /* send file */
X  			   XMITTYPE = gettype(argv[1][index++]);
X  			   break;
X+ 		case 'p':  /* TIP */
X+ 		case 'P':
X+ 		           INFD = 3;
X+ 			   OUTFD = 4;
X+ 			   FDS_DISTINCT = TRUE;
X+ 			   break;
X  		default  : fprintf(stderr, "Invalid Flag %c ignored\n", flag);
X  			   break;
X  	   }
X***************
X*** 120,133 ****
X  		LOGFP = fopen(fname, "w");  /* new LOG file */
X  	     if (!LOGFP)
X  		error("Fatal - Can't Open Log File", FALSE);
X  
X  	     fprintf(LOGFP,"\n++++++++  %s", stamptime());
X  	     fprintf(LOGFP,"XMODEM Version %d.%d\n", VERSION/10, VERSION%10);
X  	     fprintf(LOGFP,"Command line: %s %s", argv[0], argv[1]);
X! 	     for (index=2; index<argc; ++index)
X! 		fprintf(LOGFP, " %s", argv[index]);
X  	     fprintf(LOGFP, "\n");
X! 	   }
X  
X  	getspeed();		/* get tty-speed for time estimates */
X  
X--- 129,147 ----
X  		LOGFP = fopen(fname, "w");  /* new LOG file */
X  	     if (!LOGFP)
X  		error("Fatal - Can't Open Log File", FALSE);
X+ 	     setlinebuf(LOGFP);
X  
X  	     fprintf(LOGFP,"\n++++++++  %s", stamptime());
X+ 		 
X  	     fprintf(LOGFP,"XMODEM Version %d.%d\n", VERSION/10, VERSION%10);
X+ 
X  	     fprintf(LOGFP,"Command line: %s %s", argv[0], argv[1]);
X! 
X! 	     for (index=2; index<argc; ++index) {
X! 		 fprintf(LOGFP, " %s", argv[index]);
X! 	     }
X  	     fprintf(LOGFP, "\n");
X! 	 }
X  
X  	getspeed();		/* get tty-speed for time estimates */
X  
X===================================================================
XRCS file: RCS/xmodem.h,v
Xretrieving revision 1.1
Xretrieving revision 1.2
Xdiff -c -r1.1 -r1.2
X*** /tmp/,RCSt1a02154	Tue Jan  2 12:33:13 1990
X--- /tmp/,RCSt2a02154	Tue Jan  2 12:33:14 1990
X***************
X*** 10,16 ****
X  #define  logit(string) if(LOGFLAG)fprintf(LOGFP,string)
X  #define  logitarg(string,argument) if(LOGFLAG)fprintf(LOGFP,string,argument)
X  
X! #define	     VERSION	36	/* Version Number */
X  #define      FALSE      0
X  #define      TRUE       1
X  
X--- 10,16 ----
X  #define  logit(string) if(LOGFLAG)fprintf(LOGFP,string)
X  #define  logitarg(string,argument) if(LOGFLAG)fprintf(LOGFP,string,argument)
X  
X! #define	     VERSION	37	/* Version Number */
X  #define      FALSE      0
X  #define      TRUE       1
X  
X***************
X*** 73,78 ****
X--- 73,81 ----
X  int	YMDMBAT;	/* YMODEM batch protocol */
X  int	TOOBUSY;	/* turn off sleeping in packet read routine */
X  int	CHECKLENGTH;	/* Are we truncating a file to a YMODEM length? */
X+ int 	INFD;		/* file descriptor for protocol reading */
X+ int	OUTFD;		/* file descriptor for protocol reading */
X+ int     FDS_DISTINCT;   /* in,out fd's not 0 and 1 */
X  
X  
X  /*   CRC-16 constants.  From Usenet contribution by Mark G. Mendel, 
X===================================================================
XRCS file: RCS/getput.c,v
Xretrieving revision 1.1
Xretrieving revision 1.2
Xdiff -c -r1.1 -r1.2
X*** /tmp/,RCSt1a02154	Tue Jan  2 12:33:14 1990
X--- /tmp/,RCSt2a02154	Tue Jan  2 12:33:15 1990
X***************
X*** 4,9 ****
X--- 4,10 ----
X   */
X  
X  #include "xmodem.h"
X+ #include <sys/types.h>
X  
X  /*
X   *
X***************
X*** 103,113 ****
X  /* get a byte from data stream -- timeout if "seconds" elapses */
X  /* This routine is VERY 4.2 specific */
X  
X  int
X  readbyte(seconds)
X  int seconds;
X  	{
X- 	int readfd;
X  	char c;
X  	struct timeval tmout;
X  
X--- 104,122 ----
X  /* get a byte from data stream -- timeout if "seconds" elapses */
X  /* This routine is VERY 4.2 specific */
X  
X+ int select_input (tmout)
X+ struct timeval * tmout;
X+ {
X+     fd_set readfd;		/* mask for select call */
X+     FD_ZERO(&readfd);
X+     FD_SET(INFD, &readfd);
X+     return select(getdtablesize(), &readfd, (int *)0, (int *)0, tmout);
X+ }
X+ 
X  int
X  readbyte(seconds)
X  int seconds;
X  	{
X  	char c;
X  	struct timeval tmout;
X  
X***************
X*** 114,125 ****
X  	tmout.tv_sec = seconds;
X  	tmout.tv_usec = 0;
X  
X- 	readfd = 1<<0;
X  
X! 	if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
X! 		return(TIMEOUT);
X  
X! 	read(0, &c, 1);
X  
X  	if (DEBUG)
X  		fprintf(LOGFP, "DEBUG: readbyte %02xh\n", c & 0xff);
X--- 123,133 ----
X  	tmout.tv_sec = seconds;
X  	tmout.tv_usec = 0;
X  
X  
X! 	if (select_input(&tmout) == 0)
X! 	    return(TIMEOUT);
X  
X! 	read(INFD, &c, 1);
X  
X  	if (DEBUG)
X  		fprintf(LOGFP, "DEBUG: readbyte %02xh\n", c & 0xff);
X***************
X*** 138,151 ****
X  	/* set up a usec timeout on stdin */
X  	tmout.tv_sec = 0;
X  	tmout.tv_usec = 1;
X! 	readfd = 1<<0;
X  
X  	/* any characters pending?; return if none */
X! 	if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
X! 		return;
X  
X  	/* read the characters to flush them (assume there are fewer than BBUFSIZ */
X! 	(void) read(0, inbuf, BBUFSIZ);
X  	}
X--- 146,159 ----
X  	/* set up a usec timeout on stdin */
X  	tmout.tv_sec = 0;
X  	tmout.tv_usec = 1;
X! 	readfd = 1<<INFD;
X  
X  	/* any characters pending?; return if none */
X! 	if (select_input(&tmout) == 0)
X! 	    return;
X  
X  	/* read the characters to flush them (assume there are fewer than BBUFSIZ */
X! 	(void) read(INFD, inbuf, BBUFSIZ);
X  	}
X***************
X*** 170,181 ****
X  long recvsectcnt;	/* running sector count (128 byte sectors) */
X  
X  {
X- 	int readfd;		/* mask for select call */
X- 	struct timeval tmout;	/* timeout structure for select */
X  	int numread;		/* number of chars read */
X  	int left;		/* number of chars left to read */
X  	int recfin = FALSE;		/* flag that EOF read */
X  	char inbuf[BBUFSIZ];	/* buffer for incoming packet */
X  	register unsigned char c;	/* character being processed */
X  	register unsigned short chksm;	/* working copy of checksum */
X  	register int bfctr;	/* working copy of bufctr */
X--- 178,188 ----
X  long recvsectcnt;	/* running sector count (128 byte sectors) */
X  
X  {
X  	int numread;		/* number of chars read */
X  	int left;		/* number of chars left to read */
X  	int recfin = FALSE;		/* flag that EOF read */
X  	char inbuf[BBUFSIZ];	/* buffer for incoming packet */
X+ 	struct timeval tmout;	/* timeout structure for select */
X  	register unsigned char c;	/* character being processed */
X  	register unsigned short chksm;	/* working copy of checksum */
X  	register int bfctr;	/* working copy of bufctr */
X***************
X*** 184,190 ****
X  
X  	tmout.tv_sec = seconds;
X  	tmout.tv_usec = 0;
X- 	readfd = 1<<0;
X  	chksm = 0;
X  	bfctr = 0;
X  
X--- 191,196 ----
X***************
X*** 192,201 ****
X  
X  		/* read however many chars are waiting */
X  
X! 		if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
X! 			return(TIMEOUT);
X  
X! 		numread = read(0, inbuf, left);
X  		left -= numread;
X  
X  		if (DEBUG)
X--- 198,207 ----
X  
X  		/* read however many chars are waiting */
X  
X! 		if (select_input(&tmout) == 0)
X! 		    return(TIMEOUT);
X  
X! 		numread = read(INFD, inbuf, left);
X  		left -= numread;
X  
X  		if (DEBUG)
X***************
X*** 275,281 ****
X  	if (DEBUG)
X  		fprintf(LOGFP, "DEBUG: sendbyte %02xh\n", data & 0xff);
X  
X! 	if (write(1, &data, 1) != 1)  	/* write the byte (assume it goes NOW; no flushing needed) */
X  		error ("Write error on stream", TRUE);
X  	return;
X  	}
X--- 281,287 ----
X  	if (DEBUG)
X  		fprintf(LOGFP, "DEBUG: sendbyte %02xh\n", data & 0xff);
X  
X! 	if (write(OUTFD, &data, 1) != 1)  	/* write the byte (assume it goes NOW; no flushing needed) */
X  		error ("Write error on stream", TRUE);
X  	return;
X  	}
X***************
X*** 289,295 ****
X  	if (DEBUG)
X  		fprintf(LOGFP, "DEBUG: writebuf (%d bytes)\n", nbytes);
X  
X! 	if (write(1, buffer, nbytes) != nbytes)		/* write the buffer (assume no TIOCFLUSH needed) */
X  		error ("Write error on stream", TRUE);
X  	return;
X  	}
X--- 295,301 ----
X  	if (DEBUG)
X  		fprintf(LOGFP, "DEBUG: writebuf (%d bytes)\n", nbytes);
X  
X! 	if (write(OUTFD, buffer, nbytes) != nbytes)		/* write the buffer (assume no TIOCFLUSH needed) */
X  		error ("Write error on stream", TRUE);
X  	return;
X  	}
X***************
X*** 302,308 ****
X  int	milliseconds;
X  {
X  	struct	timeval	timeout;
X- 	int readfd;
X  
X  	if (milliseconds == 0)
X  		return;
X--- 308,313 ----
X***************
X*** 310,318 ****
X  		fprintf (LOGFP, "DEBUG: napping for %d ms\n", milliseconds);
X  	timeout.tv_sec = 0;
X  	timeout.tv_usec = milliseconds * 1000;
X- 	readfd = 0;
X  
X! 	(void) select(1, &readfd, (int *)0, (int *)0, &timeout);
X  }
X--- 315,322 ----
X  		fprintf (LOGFP, "DEBUG: napping for %d ms\n", milliseconds);
X  	timeout.tv_sec = 0;
X  	timeout.tv_usec = milliseconds * 1000;
X  
X! 	(void) select(0, (int *)0, (int *)0, (int *)0, &timeout);
X  }
X***************
X*** 335,344 ****
X  	extern onintr();
X  
X  	sleep(2);			/* let the output appear */
X! 	if (ioctl(0,TIOCGETP,&ttys)<0)  /* get tty params [V7] */
X  		error("Can't get TTY Parameters", TRUE);
X  
X! 	tty = ttyname(0);  /* identify current tty */
X  	
X  	ttysnew.sg_ispeed = ttys.sg_ispeed;	/* copy input speed */
X  	ttysnew.sg_ospeed = ttys.sg_ospeed;	/* copy input speed */
X--- 339,348 ----
X  	extern onintr();
X  
X  	sleep(2);			/* let the output appear */
X! 	if (ioctl(INFD,TIOCGETP,&ttys)<0)  /* get tty params [V7] */
X  		error("Can't get TTY Parameters", TRUE);
X  
X! 	tty = ttyname(INFD);  /* identify current tty */
X  	
X  	ttysnew.sg_ispeed = ttys.sg_ispeed;	/* copy input speed */
X  	ttysnew.sg_ospeed = ttys.sg_ospeed;	/* copy input speed */
X***************
X*** 347,358 ****
X  	ttysnew.sg_flags &= ~TANDEM;	/* turn off flow control */
X  
X  	/* set new paramters */
X! 	if (ioctl(0,TIOCSETP,&ttysnew) < 0)
X  		error("Can't set new TTY Parameters", TRUE);
X  
X  	/* Flush characters waiting for read or write */
X  	n = 0;
X! 	if (ioctl(0,TIOCFLUSH,&n) < 0)
X  		error("Can't flush terminal queue", TRUE);
X  
X  	/* get tty status */ 
X--- 351,362 ----
X  	ttysnew.sg_flags &= ~TANDEM;	/* turn off flow control */
X  
X  	/* set new paramters */
X! 	if (ioctl(INFD,TIOCSETP,&ttysnew) < 0)
X  		error("Can't set new TTY Parameters", TRUE);
X  
X  	/* Flush characters waiting for read or write */
X  	n = 0;
X! 	if (ioctl(INFD,TIOCFLUSH,&n) < 0)
X  		error("Can't flush terminal queue", TRUE);
X  
X  	/* get tty status */ 
X***************
X*** 381,387 ****
X  	if (wason)
X  		if (chmod(tty, (int)statbuf.st_mode | 022) < 0)
X  			error("Can't change TTY mode", FALSE);
X! 	if (ioctl(0,TIOCSETP,&ttys) < 0)
X  		{ if (!errcall)
X  		   error("RESET - Can't restore normal TTY Params", FALSE);
X  		else
X--- 385,391 ----
X  	if (wason)
X  		if (chmod(tty, (int)statbuf.st_mode | 022) < 0)
X  			error("Can't change TTY mode", FALSE);
X! 	if (ioctl(INFD,TIOCSETP,&ttys) < 0)
X  		{ if (!errcall)
X  		   error("RESET - Can't restore normal TTY Params", FALSE);
X  		else
X***************
X*** 423,429 ****
X  	{
X  	static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 
X  	   1200, 1800, 2400, 4800, 9600, 19200, 0};
X! 	if (ioctl(0,TIOCGETP,&ttys) < 0)	/* get tty structure */
X  		error("Can't get TTY parameters", FALSE);
X  
X  	if (ttys.sg_ispeed >= 0 && ttys.sg_ispeed <= 14)
X--- 427,433 ----
X  	{
X  	static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 
X  	   1200, 1800, 2400, 4800, 9600, 19200, 0};
X! 	if (ioctl(INFD,TIOCGETP,&ttys) < 0)	/* get tty structure */
X  		error("Can't get TTY parameters", FALSE);
X  
X  	if (ttys.sg_ispeed >= 0 && ttys.sg_ispeed <= 14)
X
X--------------------------------------------------------------------------------
X
Xxmodem Program history:
X
XDescended from UMODEM 3.5 by Lauren Weinstein, Richard Conn, and others.
X
XBased on XMODEM Version 1.0 by Brian Kantor, UCSD (3/84)  (Don't blame him 
X    in any way for what follows....)
X
XVersion 2.0 (CRC-16 and Modem7 batch file transfer) (5/85) (Thanks to D'Anne
X    Thompson for the batch transfer code).
X
XVersion 2.1 (1K packets) (7/85)
X
XVersion 2.2 (general clean-ups and multi-character read speed-ups) (9/85)
X
XVersion 2.3 (nap while reading packets; split into several source files) (1/86)
X
XVersion 3.0 (Ymodem batch receive; associated changes) (2/86)
X
XVersion 3.1 (Ymodem batch send; associated changes) (8/86)
X
XVersion 3.2 (general cleanups) (9/86) 
X    (Released to the world 1/87)
X
XVersion 3.3 (general fixes and cleanups; see update.doc) (5/87)
X
XVersion 3.4 (general fixes and cleanups; see update.doc) (10/87) 
X    (Released to the world 3/88)
X
XVersion 3.5 (general fixes and cleanups; see update.doc) (3/88)
X
XVersion 3.6 (general fixes and cleanups; text file translation for Mac; 
X    see update.doc) (4/88) 
X    (Released to the world 4/88)
X
XVersion 3.7 (general fixes and cleanups; see update.doc) (5/88)
X
XVersion 3.8 (general fixes and cleanups; see update.doc) (11/88)
X
XVersion 3.9 (general fixes and cleanups; Sun tip support; 
X    see update.doc) (11/90)
X
X--------------------------------------------------------------------------------
X
XPlease send bug fixes, additions and comments to:
XSteve Grandi, National Optical Astronomy Observatories (Tucson, Arizona, USA)
X	grandi at noao.edu
END_OF_FILE
  if test 21493 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
  fi
  # end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
  echo shar: Extracting \"'Makefile'\" \(914 characters\)
  sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XOBJECTS = xmodem.o getput.o misc.o send.o receive.o batch.o
XCFLAGS = -O
X
Xxmodem: $(OBJECTS)
X	cc $(CFLAGS) $(OBJECTS) -o xmodem
X
X$(OBJECTS): xmodem.h
X
Xprint: 
X	lpr -p -Pvmslp xmodem.h xmodem.c getput.c receive.c send.c batch.c \
X	misc.c Makefile update.doc README xmodem.1 getput.sysv.c
X
Xlint:
X	lint xmodem.c getput.c receive.c send.c batch.c misc.c | imprint
X
Xshar:
X	shar README Makefile xmodem.1 xmodem.h > xmodem.shar.1
X	shar update.doc xmodem.c receive.c > xmodem.shar.2
X	shar getput.c getput.sysv.c > xmodem.shar.3
X	shar misc.c batch.c send.c > xmodem.shar.4
X	shar ymodem.doc > xmodem.shar.5
X
Xbigshar: 
X	shar README update.doc Makefile xmodem.1 xmodem.h xmodem.c getput.c \
X	getput.sysv.c receive.c misc.c batch.c send.c > xmodem.shar
X
Xtarz: 
X	tar cvf xmodem.tar README update.doc Makefile xmodem.1 xmodem.h \
X	xmodem.c getput.c getput.sysv.c receive.c misc.c batch.c send.c \
X	ymodem.doc
X	compress xmodem.tar
END_OF_FILE
  if test 914 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
  fi
  # end of 'Makefile'
fi
if test -f 'receive.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'receive.c'\"
else
  echo shar: Extracting \"'receive.c'\" \(17709 characters\)
  sed "s/^X//" >'receive.c' <<'END_OF_FILE'
X#include "xmodem.h"
X
X/**  receive a file  **/
X
X/* returns TRUE if in the midst of a batch transfer */
X/* returns FALSE if no more files are coming */
X
X/* This routine is one HUGE do-while loop with far to many indented levels.
X * I chose this route to facilitate error processing and to avoid GOTOs.
X * Given the troubles I've had keeping the nested IF statements straight,
X * I was probably mistaken...
X */
X
Xrfile(name)
Xchar *name;
X{
X
Xchar *sectdisp();
Xchar *cpm_unix();
Xchar *strcpy();
Xchar *ctime();
Xtime_t time();
X
Xint fd,     /* file descriptor for created file */
Xchecksum,   /* packet checksum */
Xfirstchar,  /* first character of a packet */
Xsectnum,    /* number of last received packet (modulo 128) */
Xsectcurr,   /* second byte of packet--should be packet number (mod 128) */
Xsectcomp,   /* third byte of packet--should be complement of sectcurr */
Xtmode,      /* text mode if true */
Xamode,      /* apple mode if true */
Xerrors,     /* count of errors for each packet */
Xsterrors,   /* count of errors during startup handshake */
Xerrorflag,  /* set true when packet (or first char of putative packet) is invalid */
Xfatalerror, /* set within main "read-packet" Do-While when bad error found */
Xinchecksum, /* incoming checksum or CRC */
Xexpsect,    /* expected number of sectors (YMODEM batch) */
Xfirstwait,  /* seconds to wait for first character in a packet */
Xnocancanabort, /* if true, don't allow CAN-CAN abort */
Xbufsize;    /* packet size (128 or 1024) */
Xlong recvsectcnt;   /* running sector count (128 byte sectors) */
Xlong modtime;       /* Unix style file mod time from YMODEM header */
Xint filemode;       /* Unix style file mode from YMODEM header */
Xint serial;	/* serial # from YMODEM header */
Xint filesleft;		/* # of files left from YMODEM header */
Xlong totalleft;		/* # of bytes left from YMODEM header */
Xint yfiletype;		/* file type from YMODEM header */
Xlong readbackup;    /* "backup" value for characters read in file */
Xtime_t timep[2];    /* used in setting mod time of received file */
Xchar *p;    /* generic pointer */
Xint bufctr; /* number of real chars in read packet */
Xunsigned char *nameptr; /* ptr in filename for MODEM7 protocol */
Xtime_t start;       /* starting time of transfer */
Xint openflag = FALSE;   /* is file open for writing? */
X
Xlogit("----\nXMODEM File Receive Function\n");
Xtlogit("----\nXMODEM File Receive Function\n");
Xif (CRCMODE)
X	{
X	logit("CRC mode requested on command line\n");
X	tlogit("CRC mode requested on command line\n");
X	}
X
Xif (YMODEMG)
X	{
X	logit("YMODEM-G mode requested on command line\n");
X	tlogit("YMODEM-G mode requested on command line\n");
X	}
X
XBATCH = FALSE;          /* don't know if really are in batch mode ! */
Xfatalerror = FALSE;
Xfirstwait = WAITFIRST;  /* For first packet, wait short time */
Xsectnum = errors = recvsectcnt = 0;
Xbufsize = 128;
Xmodtime = 0l; filemode = 0;
Xserial = 0; filesleft = 0; totalleft = 0l; yfiletype = 0;
Xfilelength = 0l; fileread =0l; CHECKLENGTH = FALSE;
Xnocancanabort = FALSE;
X
Xtmode = (XMITTYPE == 't') ? TRUE : FALSE;
Xamode = (XMITTYPE == 'a') ? TRUE : FALSE;
X
X/* start up transfer */
X
Xsterrors = 0;
Xflushin();         /* flush input queue */
X
Xif (YMODEMG)
X	sendbyte(GCHR);
Xelse if (CRCMODE && !MDM7BAT)        
X{
X	sendbyte(CRCCHR);
X	if (LONGPACK && !MDM7BAT)
X		sendbyte(KCHR);
X}
Xelse
X	sendbyte(NAK);
X
X
Xdo                  /* start of MAIN Do-While loop to read packets */
X{   
X	errorflag = FALSE;
X	do              /* start by reading first byte in packet */
X	{
X		firstchar = readbyte(firstwait);
X	} 
X	while ((firstchar != SOH) 
X	    && (firstchar != STX) 
X	    && (firstchar != EOT) 
X	    && (firstchar != ACK || recvsectcnt > 0) 
X	    && (firstchar != TIMEOUT) 
X	    && (firstchar != CAN || nocancanabort));
X
X	if (firstchar == EOT && !NOEOT)           /* check for REAL EOT */
X	{
X		flushin();
X		sendbyte(NAK);              /* NAK the EOT */
X		if ((firstchar = readbyte(5)) != EOT)   /* check next character */
X		{
X			logit("Spurious EOT detected; ignored\n");
X			tlogit("Spurious EOT detected; ignored\n");
X			if ((firstchar == SOH) || (firstchar == STX) ||
X			    (firstchar == ACK && recvsectcnt == 0) ||
X			    (firstchar == CAN && !nocancanabort) ||
X			    (firstchar == TIMEOUT))
X				;
X			else
X			{
X				firstchar = 0;
X				errorflag = TRUE;
X			}
X		}
X	}
X
X	if (firstchar == TIMEOUT)       /* timeout? */
X	{  
X		if (recvsectcnt > 0)
X			{
X			logitarg("Timeout on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
X			tlogitarg("Timeout on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
X			}
X		errorflag = TRUE;
X	}
X
X	if (firstchar == CAN)           /* bailing out? (only at beginning or if CANCAN flag set) */
X	{
X		if ((readbyte(3) & 0x7f) == CAN)
X			{
X			if (openflag)
X				{
X				close(fd);
X				unlink(name);
X				error("Reception Canceled by CAN-CAN; partial file deleted",TRUE);
X				}
X			else
X				error("Reception Canceled by CAN-CAN",TRUE);
X			}
X		else
X		{
X			errorflag = TRUE;
X			logit("Received single CAN character\n");
X			tlogit("Received single CAN character\n");
X		}
X	}
X
X	if (firstchar == ACK)           /* MODEM7 batch? (only at beginning) */
X	{
X		int i,c; 
X
X		logit("MODEM7 Batch Protocol\n");
X		tlogit("MODEM7 Batch Protocol\n");
X		nameptr = buff;
X		checksum = 0;
X
X		for (i=0; i<NAMSIZ; i++)
X		{
X			c = readbyte(3);
X
X			if (c == CAN)
X			{
X				if (readbyte(3) == CAN)
X					error("Program Canceled by CAN-CAN", TRUE);
X				else
X				{
X					logit("Received single CAN character in MODEM7 filename\n");
X					tlogit("Received single CAN character in MODEM7 filename\n");
X					errorflag = TRUE;
X					break;
X				}
X			}
X
X			if (c == EOT && i == 0)
X			{
X				sendbyte(ACK);          /* acknowledge EOT */
X				logit("MODEM7 Batch Receive Complete\n");
X				tlogit("MODEM7 Batch Receive Complete\n");
X				return (FALSE);
X			}
X
X			if (c == TIMEOUT)
X			{
X				logit("Timeout waiting for MODEM7 filename character\n");
X				tlogit("Timeout waiting for MODEM7 filename character\n");
X				errorflag = TRUE;
X				break;
X			}
X
X			if (c == BAD_NAME)
X			{
X				logit("Error during MODEM7 filename transfer\n");
X				tlogit("Error during MODEM7 filename transfer\n");
X				errorflag = TRUE;
X				break;
X			}
X
X			*nameptr++ = c;
X			checksum += c;
X			sendbyte(ACK);
X		}
X
X		if (!errorflag)
X		{
X			c = readbyte(3);
X			if (c == CTRLZ)     /* OK; end of string found */
X			{
X				sendbyte(checksum + CTRLZ);
X				if (readbyte(15) == ACK)     /* file name found! */
X				{
X					xmdebug("MODEM7 file name OK");
X					*nameptr = '\000';  /* unixify the file name */
X					name = cpm_unix(buff);
X					BATCH = TRUE;
X					logitarg("MODEM7 file name: %s\n", name);
X					tlogitarg("MODEM7 file name: %s\n", name);
X					errors = 0;     /* restart crc handshake */
X					sleep(2);       /* give other side a chance */
X				}
X				else
X				{
X					logit("Checksum error in MODEM7 filename\n");
X					tlogit("Checksum error in MODEM7 filename\n");
X					errorflag = TRUE;
X				}
X			}
X			else
X			{
X				logit("Length error in MODEM7 filename\n");
X				tlogit("Length error in MODEM7 filename\n");
X				errorflag = TRUE;
X			}
X		}
X	}
X
X
X	if (firstchar == SOH || firstchar == STX)  /* start reading packet */
X	{
X		bufsize = (firstchar == SOH) ? 128 : 1024;
X
X		if (recvsectcnt == 0)           /* 1st data packet, initialize */
X		{
X			if (bufsize == 1024)
X				{
X				logit("1K packet mode chosen\n");
X				tlogit("1K packet mode chosen\n");
X				}
X			start = time((time_t *) 0);
X			errors = 0;
X			firstwait = 5;
X		}
X
X		sectcurr = readbyte(3);
X		sectcomp = readbyte(3);
X		if ((sectcurr + sectcomp) == 0xff)  /* is packet number checksum correct? */
X		{  
X			if (sectcurr == ((sectnum+1) & 0xff))   /* is packet number correct? */
X			{  
X				if (DEBUG)
X					fprintf(LOGFP,"DEBUG: packet with sector number %d started\n", sectnum);
X
X				/* Read, process and calculate checksum for a buffer of data */
X
X				readbackup = fileread;
X				if (readbuf(bufsize, 1, tmode, amode, recvsectcnt, &checksum, &bufctr) != TIMEOUT) 
X				{
X
X					/* verify checksum or CRC */
X
X					if (CRCMODE) 
X					{
X						checksum &= 0xffff;
X						inchecksum = readbyte(3);  /* get 16-bit CRC */
X						inchecksum = (inchecksum<<8) | readbyte(3);
X					}
X
X					else
X						inchecksum = readbyte(3);  /* get simple 8-bit checksum */
X
X					if (inchecksum == checksum) /* good checksum, hence good packet */
X					{  
X						xmdebug("checksum ok");
X						errors = 0;
X						recvsectcnt += (bufsize == 128) ? 1 : 8;
X						nocancanabort = CANCAN ? FALSE : TRUE;
X						sectnum = sectcurr; 
X
X						if (!openflag)      /* open output file if necessary */
X						{
X							openflag = TRUE;
X							if ((fd = creat(name, CREATMODE)) < 0)
X							{
X								sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X								error("Can't create file for receive", TRUE);
X							}
X							if (!BATCH)
X								{
X								logitarg("File Name: %s\n", name);
X								tlogitarg("File Name: %s\n", name);
X								}
X						}
X
X						if (write(fd, (char *) buff, bufctr) != bufctr)
X						{
X							close(fd);
X							unlink(name);
X							error("File Write Error", TRUE);
X						}
X						else
X						{
X							if (TIPFLAG && recvsectcnt % 32 == 0)
X								tlogitarg("Sector %s received\n", sectdisp(recvsectcnt,bufsize,0));
X							if (!YMODEMG)
X								{
X								flushin();          /* flush input */
X								sendbyte(ACK);      /* ACK the received packet */
X								}
X						}
X					}
X
X					/* Start handling various errors and special conditions */
X
X					else        /* bad checksum */
X					{  
X						logitarg("Checksum Error on Sector %s:  ", sectdisp(recvsectcnt,bufsize,1));
X						logitarg("sent=%x  ", inchecksum);
X						logitarg("recvd=%x\n", checksum);
X						tlogitarg("Checksum Error on Sector %s:  ", sectdisp(recvsectcnt,bufsize,1));
X						tlogitarg("sent=%x  ", inchecksum);
X						tlogitarg("recvd=%x\n", checksum);
X						fileread = readbackup;
X						errorflag = TRUE;
X						if (YMODEMG)
X							fatalerror = TRUE;
X					}
X				}
X
X				else    /* read timeout */
X				{
X					logitarg("Timeout while reading sector %s\n",sectdisp(recvsectcnt,bufsize,1));
X					tlogitarg("Timeout while reading sector %s\n",sectdisp(recvsectcnt,bufsize,1));
X					fileread = readbackup;
X					errorflag = TRUE;
X					if (YMODEMG)
X						fatalerror = TRUE;
X				}
X			}
X
X			else        /* sector number is wrong OR Ymodem filename */
X			{ 
X				if (sectcurr == 0 && recvsectcnt == 0)  /* Ymodem file-name packet */
X				{
X					logit("YMODEM Batch Protocol\n");
X					tlogit("YMODEM Batch Protocol\n");
X
X					/* Read and process a file-name packet */
X
X					if (readbuf(bufsize, 1, FALSE, FALSE, recvsectcnt, &checksum, &bufctr) != TIMEOUT) 
X					{
X
X						/* verify checksum or CRC */
X
X						if (CRCMODE) 
X						{
X							checksum &= 0xffff;
X							inchecksum = readbyte(3);  /* get 16-bit CRC */
X							inchecksum = (inchecksum<<8) | readbyte(3);
X						}
X
X						else
X							inchecksum = readbyte(3);  /* get simple 8-bit checksum */
X
X						if (inchecksum == checksum) /* good checksum, hence good filename */
X						{
X							xmdebug("checksum ok");
X							strcpy(name, (char *)buff);
X							expsect = ((buff[bufsize-1]<<8) | buff[bufsize-2]);
X							BATCH = TRUE;
X							YMDMBAT = TRUE;
X							if (strlen(name) == 0)  /* check for no more files */
X							{
X								flushin();          /* flush input */
X								sendbyte(ACK);      /* ACK the packet */
X								logit("YMODEM Batch Receive Complete\n");
X								tlogit("YMODEM Batch Receive Complete\n");
X								return (FALSE);
X							}
X							unixify(name);       /* make filename canonical */
X
X							/* read rest of YMODEM header */
X							p = (char *)buff + strlen((char *)buff) + 1;
X							if (DEBUG)
X								fprintf(LOGFP, "DEBUG: header info: %s\n", p);
X							sscanf(p, "%ld%lo%o%o%d%ld%d", 
X							  &filelength, &modtime, &filemode, 
X							  &serial, &filesleft, &totalleft,
X							  &yfiletype);
X							logitarg("YMODEM file name: %s\n", name);
X							tlogitarg("YMODEM file name: %s\n", name);
X							fileread = 0l;
X							if (filelength)
X							{
X								CHECKLENGTH = TRUE;
X								logitarg("YMODEM file size: %ld\n", filelength);
X								tlogitarg("YMODEM file size: %ld\n", filelength);
X							}
X							else if (expsect)
X								logitarg("YMODEM estimated file length %d sectors\n", expsect);
X							if (modtime)
X							{
X								logitarg("YMODEM file date: %s", ctime((time_t *)&modtime));
X							}
X							if (filemode)
X								logitarg("YMODEM file mode: %o\n", filemode);
X
X							if (filesleft)
X							{
X								logitarg("YMODEM %d file(s) left to receive ", filesleft);
X								logitarg("containing %ld bytes\n", totalleft);
X								tlogitarg("YMODEM %d file(s) left to receive ", filesleft);
X								tlogitarg("containing %ld bytes\n", totalleft);
X							}
X							if (serial)
X								logitarg("YMODEM sender's serial number: %d\n", serial);
X							if (yfiletype)
X								logitarg("YMODEM file type %d\n", yfiletype);
X
X							openflag = TRUE;	/* open the file for writing */
X							if ((fd = creat(name, CREATMODE)) < 0)
X							{
X								sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X								error("Can't create file for receive", TRUE);
X							}
X							if (!YMODEMG)
X								{
X								flushin();		/* flush the input stream */
X								sendbyte(ACK);		/* ACK the filename packet */
X								}
X							/* do initial handshake to start file transfer */
X							if (YMODEMG)
X								sendbyte(GCHR);
X							else if (CRCMODE) 
X							{
X								sendbyte(CRCCHR);
X								if (LONGPACK)
X									sendbyte(KCHR);
X							}
X							else
X								sendbyte(NAK);
X							firstwait = WAITFIRST;  /* reset waiting time */
X						}
X
X						else                /* bad filename checksum */
X						{
X							logit("checksum error on filename sector\n");
X							tlogit("checksum error on filename sector\n");
X							errorflag = TRUE;
X							if (YMODEMG)
X								fatalerror = TRUE;
X						}
X					}
X					else
X					{
X						logit("Timeout while reading filename packet\n");
X						tlogit("Timeout while reading filename packet\n");
X						errorflag = TRUE;
X						if (YMODEMG)
X							fatalerror = TRUE;
X					}
X				}
X
X				else if (sectcurr == sectnum)   /* duplicate sector? */
X				{  
X					logitarg("Duplicate sector %s flushed\n", sectdisp(recvsectcnt,bufsize,0));
X					tlogitarg("Duplicate sector %s flushed\n", sectdisp(recvsectcnt,bufsize,0));
X					if (YMODEMG)
X						{
X						errorflag = TRUE;
X						fatalerror = TRUE;
X						}
X					else
X						{
X						flushin();                  /* REALLY flush input */
X						while(readbyte(1) != TIMEOUT)
X							;
X						sendbyte(ACK);
X						}
X				}
X				else                /* no, real phase error */
X				{
X					logitarg("Phase Error - Expected packet is %s\n", sectdisp(recvsectcnt,bufsize,1));
X					tlogitarg("Phase Error - Expected packet is %s\n", sectdisp(recvsectcnt,bufsize,1));
X					errorflag = TRUE;
X					fatalerror = TRUE;
X				}
X			}
X		}
X
X		else        /* bad packet number checksum */
X		{  
X			logitarg("Header Sector Number Error on Sector %s\n", sectdisp(recvsectcnt, bufsize,1));
X			tlogitarg("Header Sector Number Error on Sector %s\n", sectdisp(recvsectcnt, bufsize,1));
X			errorflag = TRUE;
X			if (YMODEMG)
X				fatalerror = TRUE;
X		}
X
X	}           /* END reading packet loop */
X
X	if (errorflag && !fatalerror && recvsectcnt != 0)   /* Handle errors */
X	{  
X		errors++;
X
X		if (errors >= ERRORMAX)     /* over error limit? */
X			fatalerror = TRUE;
X		else                        /* flush input and NAK the packet */
X		{
X			flushin();
X			while (readbyte(2) != TIMEOUT)  /* wait for line to settle */
X				;
X			sendbyte(NAK);
X		}
X	}
X
X	if (recvsectcnt == 0 && errorflag && !fatalerror && firstchar != EOT) 	/* handle startup handshake */
X	{
X		sterrors++;
X
X		if (sterrors >= STERRORMAX)
X			fatalerror = TRUE;
X
X		else if (CRCMODE && MDM7BAT && !BATCH)
X			sendbyte(NAK);
X		
X		else if (CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
X		{
X			CRCMODE = FALSE;
X			logit("Sender not accepting CRC request, changing to checksum\n");
X			tlogit("Sender not accepting CRC request, changing to checksum\n");
X			sendbyte(NAK);
X		}
X
X		else if (!CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
X		{
X			CRCMODE = TRUE;
X			logit("Sender not accepting checksum request, changing to CRC\n");
X			tlogit("Sender not accepting checksum request, changing to CRC\n");
X			sendbyte(CRCCHR);
X			if (LONGPACK && !MDM7BAT)
X				sendbyte(KCHR);
X		}
X
X		else if (YMODEMG)
X			sendbyte(GCHR);
X
X		else if (CRCMODE)
X			{
X			sendbyte(CRCCHR);
X			if (LONGPACK && !MDM7BAT)
X				sendbyte(KCHR);
X			}
X
X		else
X			sendbyte(NAK);
X	}
X}
Xwhile ((firstchar != EOT) && !fatalerror);   /* end of MAIN Do-While */
X
Xif ((firstchar == EOT) && !fatalerror)  /* normal exit? */
X{
X	if (openflag)       /* close the file */
X		close(fd);
X	sendbyte(ACK);      /* ACK the EOT */
X	logit("Receive Complete\n");
X	tlogit("Receive Complete\n");
X	if (LOGFLAG)
X		prtime (recvsectcnt, time((time_t *) 0) - start, LOGFP);
X	if (TIPFLAG)
X		prtime (recvsectcnt, time((time_t *) 0) - start, stderr);
X
X	if (openflag && modtime)   /* set file modification time */
X	{
X		timep[0] = time((time_t *) 0);
X		timep[1] = modtime;
X		utime(name, timep);
X	}
X
X	if (BATCH)          /* send appropriate return code */
X		return(TRUE);
X	else
X		return(FALSE);
X}
Xelse                /* no, error exit */
X{ 
X	if (openflag)
X	{
X		sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X		close(fd);
X		unlink(name);
X		flushin();
X		while (readbyte(2) != TIMEOUT)  /* wait for line to settle */
X			;
X		error("ABORTED -- Too Many Errors -- Deleting File", TRUE);
X	}
X	else if (recvsectcnt != 0)
X		{
X		sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X		flushin();
X		while (readbyte(2) != TIMEOUT)  /* wait for line to settle */
X			;
X		error("ABORTED -- Too Many Errors", TRUE);
X		}
X	else
X		{
X		flushin();
X		while (readbyte(2) != TIMEOUT)  /* wait for line to settle */
X			;
X		error("ABORTED -- Remote system is not responding", TRUE);
X		}
X
X}
X
Xreturn(FALSE);
X}
END_OF_FILE
  if test 17709 -ne `wc -c <'receive.c'`; then
    echo shar: \"'receive.c'\" unpacked with wrong size!
  fi
  # end of 'receive.c'
fi
if test -f 'xmodem.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xmodem.c'\"
else
  echo shar: Extracting \"'xmodem.c'\" \(8438 characters\)
  sed "s/^X//" >'xmodem.c' <<'END_OF_FILE'
X/*
X *  XMODEM -- Implements the Christensen XMODEM protocol, 
X *            for packetized file up/downloading.    
X *
X *	See the README file for some notes on SYS V adaptations.
X *	The program has been successfully run on VAXes (4.3BSD) and SUN-3/4s
X *	(SunOS 3.x) against MEX-PC and ZCOMM/DSZ.
X *
X *  See the README and update.doc files for history and change notes.
X *
X *  Please send bug fixes, additions and comments to:
X *	grandi at noao.edu
X */
X
X#include "xmodem.h"
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	char *getenv();
X	FILE *fopen();
X	char *unix_cpm();
X	char *strcpy();
X	char *strcat();
X	char *prtype();
X	
X	char *fname = filename;		/* convenient place to stash file names */
X	char *logfile = "xmodem.log";	/* Name of LOG File */
X	
X	char *stamptime();		/* for timestamp */
X
X	char *defname = "xmodem.in";	/* default file name if none given */
X
X	struct stat filestatbuf;	/* file status info */
X
X	int index;
X	char flag;
X	long expsect;
X	int fd;
X
X	/* initialize option flags */
X
X	XMITTYPE = 't';		/* assume text transfer */
X	DEBUG = FALSE;		/* keep debugging info in log */
X	RECVFLAG = FALSE;	/* not receive */
X	SENDFLAG = FALSE;	/* not send either */
X	BATCH = FALSE;		/* nor batch */
X	CRCMODE = FALSE;	/* use checksums for now */
X	DELFLAG = FALSE;	/* don't delete old log file */
X	LOGFLAG = TRUE;		/* keep log */
X	LONGPACK = FALSE; 	/* do not use long packets on transmit */
X	MDM7BAT = FALSE;	/* no MODEM7 batch mode */
X	YMDMBAT = FALSE;	/* no YMODEM batch mode */
X	TOOBUSY = FALSE;	/* not too busy for sleeping in packet read */
X	TIPFLAG = FALSE;	/* no special logging on stderr */
X	DELAYFLAG = FALSE;	/* don't delay startup for a while */
X	NOEOT = FALSE;		/* don't suppress EOT verification */
X	CANCAN = FALSE;		/* don't allow CAN-CAN aborts in mid-transfer */
X	YMODEMG = FALSE;	/* no YMODEM-G */
X
X	fprintf(stderr, "XMODEM Version %s", VERSION);
X	fprintf(stderr, " -- UNIX-Microcomputer File Transfer Facility\n");
X
X	if (argc == 1)
X		{
X		help();
X		exit(-1);
X		}
X
X	index = 0;		/* set index for flag loop */
X
X	stopsig();		/* suppress keyboard stop signal */
X
X	while ((flag = argv[1][index++]) != '\0')
X	    switch (flag) {
X		case '-' : break;
X		case 'X' :
X		case 'x' : DEBUG = TRUE;  /* turn on debugging log */
X			   break;
X		case 'C' :
X		case 'c' : CRCMODE = TRUE; /* enable CRC on receive */
X			   break;
X		case 'D' :
X		case 'd' : DELFLAG = TRUE;  /* delete log file */
X			   break;
X		case 'L' :
X		case 'l' : LOGFLAG = FALSE;  /* turn off log  */
X			   break;
X		case 'm' :
X		case 'M' : MDM7BAT = TRUE;  /* turn on MODEM7 batch protocol */
X			   BATCH   = TRUE;
X			   break;
X		case 'y' :
X		case 'Y' : YMDMBAT = TRUE;  /* turn on YMODEM batch protocol */
X			   BATCH   = TRUE;
X			   break;
X		case 'k' :
X		case 'K' : LONGPACK = TRUE;  /* use 1K packets on transmit */
X			   break;
X		case 't' :
X		case 'T' : TOOBUSY = TRUE;  /* turn off sleeping */
X			   break;
X		case 'p' :
X		case 'P' : TIPFLAG = TRUE;  /* turn on special handling for SunOS tip */
X			   break;
X		case 'w' :
X		case 'W' : DELAYFLAG = TRUE;  /* delay startup */
X			   break;
X		case 'e' :
X		case 'E' : NOEOT = TRUE;  /* turn off EOT verification */
X			   break;
X		case 'n' :
X		case 'N' : CANCAN = TRUE;  /* allow mid-transfer CAN-CAN */
X			   break;
X		case 'g' :
X		case 'G' : YMODEMG = TRUE;  /* YMODEM-G mode */
X			   CANCAN = TRUE;
X			   CRCMODE = TRUE;
X			   YMDMBAT = TRUE;
X			   break;
X		case 'R' :
X		case 'r' : RECVFLAG = TRUE;  /* receive file */
X			   XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
X			   break;
X		case 'S' :
X		case 's' : SENDFLAG = TRUE;  /* send file */
X			   XMITTYPE = gettype(argv[1][index++]);
X			   break;
X		default  : fprintf(stderr, "Invalid Flag %c ignored\n", flag);
X			   break;
X	   }
X
X	if (DEBUG)
X		LOGFLAG = TRUE;
X
X	if (LOGFLAG)
X	   { 
X	     if ((fname = getenv("HOME")) == 0)	/* Get HOME variable */
X		error("XMODEM Fatal Error- Can't get Environment!", FALSE);
X	     fname = strcat(fname, "/");
X	     fname = strcat(fname, logfile);
X	     if (!DELFLAG)
X		LOGFP = fopen(fname, "a");  /* append to LOG file */
X	     else
X		LOGFP = fopen(fname, "w");  /* new LOG file */
X	     if (!LOGFP)
X		error("XMODEM Fatal Error- Can't Open Log File", FALSE);
X
X	     fprintf(LOGFP,"\n++++++++  %s", stamptime());
X	     fprintf(LOGFP,"XMODEM Version %s\n", VERSION);
X	     fprintf(LOGFP,"Command line: %s %s", argv[0], argv[1]);
X	     for (index=2; index<argc; ++index)
X		fprintf(LOGFP, " %s", argv[index]);
X	     fprintf(LOGFP, "\n");
X	   }
X
X	getspeed();		/* get tty-speed for time estimates */
X
X	if (RECVFLAG && SENDFLAG)
X		error("XMODEM Fatal Error- Both Send and Receive Functions Specified", FALSE);
X
X	if (MDM7BAT && (YMDMBAT || YMODEMG))
X		error("XMODEM Fatal Error - Both YMODEM and MODEM7 Batch Protocols Specified", FALSE);
X
X	if (!RECVFLAG && !SENDFLAG)
X		error("XMODEM Fatal Error - Either Send or Receive Function must be chosen!",FALSE);
X	
X	if (SENDFLAG && argc==2)
X		error("XMODEM Fatal Error - No file specified to send",FALSE);
X
X	if (RECVFLAG && argc==2)
X		{
X		/* assume we really want CRC-16 in batch, unless we specify MODEM7 mode, unless we explicitly set CRCMODE */ 
X		if (!CRCMODE)
X			CRCMODE = MDM7BAT ? FALSE : TRUE;
X		fprintf(stderr, "Ready for BATCH RECEIVE");
X		fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
X		if (!TIPFLAG)
X			fprintf(stderr, "Send several Control-X characters to cancel\n");
X		logit("Batch Receive Started");
X		logitarg(" in %s mode\n", prtype(XMITTYPE));
X		strcpy(fname, defname);
X		}
X
X	if (RECVFLAG && argc>2)
X		{
X		if(open(argv[2], 0) != -1)  /* check for overwriting */
X			{
X			logit("Warning -- Target File Exists and is Being Overwritten\n");
X			fprintf(stderr, "Warning -- Target File Exists and is Being Overwritten\n");
X			}
X		fprintf(stderr, "Ready to RECEIVE File %s", argv[2]);
X		fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
X		if (!TIPFLAG)
X			fprintf(stderr, "Send several Control-X characters to cancel\n");
X		logitarg("Receiving in %s mode\n", prtype(XMITTYPE));
X		strcpy(fname,argv[2]);
X		}
X
X	if (RECVFLAG)
X		{  
X		if (DELAYFLAG)		/* delay if -w requested */
X			sleep(TIPDELAY);
X		setmodes();		/* set tty modes for transfer */
X
X		while(rfile(fname) != FALSE);  /* receive files */
X
X		flushin();
X		restoremodes(FALSE);	/* restore normal tty modes */
X
X		sleep(2);		/* give other side time to return to terminal mode */
X		exit(0);
X		}
X
X	if (SENDFLAG && BATCH) 
X		{
X		if (YMDMBAT)
X			{
X			ytotleft = 0l;
X			yfilesleft = 0;
X			for (index=2; index<argc; index++) {
X				if (stat(argv[index], &filestatbuf) == 0) {
X					yfilesleft++;
X					ytotleft += filestatbuf.st_size;
X					if (XMITTYPE == 't') {
X						if((fd=open(argv[index],0)) >= 0) {
X							ytotleft += countnl(fd);
X							close(fd);
X							}
X						}
X					}
X				}
X			if (DEBUG)
X				fprintf(LOGFP, "DEBUG YMODEM file count: %d, %ld bytes\n", yfilesleft, ytotleft);
X
X			fprintf(stderr, "Ready to YMODEM BATCH SEND");
X			fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
X			logit("YMODEM Batch Send Started");
X			logitarg(" in %s mode\n", prtype(XMITTYPE));
X			}
X		else if (MDM7BAT)
X			{
X			fprintf(stderr, "Ready to MODEM7 BATCH SEND");
X			fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
X			logit("MODEM7 Batch Send Started");
X			logitarg(" in %s mode\n", prtype(XMITTYPE));
X			}
X		if (!TIPFLAG)
X			fprintf(stderr, "Send several Control-X characters to cancel\n");
X
X		if (DELAYFLAG)		/* delay if -w requested */
X			sleep(TIPDELAY);
X		setmodes();
X		for (index=2; index<argc; index++) {
X			if (stat(argv[index], &filestatbuf) < 0) {
X				logitarg("\nFile %s not found\n", argv[index]);
X				tlogitarg("\nFile %s not found\n", argv[index]);
X				continue;
X			}
X			sfile(argv[index]);
X		}
X		sfile("");
X		flushin();
X		restoremodes(FALSE);
X
X		logit("Batch Send Complete\n");
X		tlogit("Batch Send Complete\n");
X		sleep(2);
X		exit (0);
X		}
X
X	if (SENDFLAG && !BATCH) 
X		{
X		if (stat(argv[2], &filestatbuf) < 0)
X			error("Can't find requested file", FALSE);
X		expsect = (filestatbuf.st_size/128)+1;
X			
X		fprintf(stderr, "File %s Ready to SEND", argv[2]);
X		fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
X		fprintf(stderr, "Estimated File Size %ldK, %ld Sectors, %ld Bytes\n",
X	    	  (filestatbuf.st_size/1024)+1, expsect,
X	  	  filestatbuf.st_size);
X		projtime(expsect, stdout);
X		if (!TIPFLAG)
X			fprintf(stderr, "Send several Control-X characters to cancel\n");
X		logitarg("Sending in %s mode\n", prtype(XMITTYPE));
X
X		setmodes();
X		sfile(argv[2]);
X		flushin();
X		restoremodes(FALSE);
X
X		sleep(2);
X		exit(0);
X		}
X}
END_OF_FILE
  if test 8438 -ne `wc -c <'xmodem.c'`; then
    echo shar: \"'xmodem.c'\" unpacked with wrong size!
  fi
  # end of 'xmodem.c'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.



More information about the Comp.sources.unix mailing list