[unix-pc.sources] xmodem v3.6

egray@fthood.UUCP (07/15/88)

This is part 2 of 3 to Steve Grandi's xmodem v3.6 package

Emmet P. Gray				US Army, HQ III Corps & Fort Hood
...!uunet!uiucuxc!fthood!egray		Attn: AFZF-DE-ENV
					Directorate of Engineering & Housing
					Environmental Management Office
					Fort Hood, TX 76544-5057

-------------------------------------------------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	misc.c
#	receive.c
#	send.c
#	xmodem.c
#	xmodem.h
#	xmodem.1
# This archive created: Thu Jul 14 13:12:46 1988
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'misc.c'" '(4381 characters)'
if test -f 'misc.c'
then
	echo shar: "will not over-write existing file 'misc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'misc.c'
X#include "xmodem.h"
X
X/*  Print Help Message  */
Xhelp()
X	{
X	fprintf(stderr, "\nUsage:  \n\txmodem ");
X	fprintf(stderr, "-[rb!rt!ra!sb!st!sa][options] filename\n");
X	fprintf(stderr, "\nMajor Commands --");
X#ifdef LOCAL
X	fprintf(stderr, "\n\tr  <-- Receive Binary");
X#else /* LOCAL */
X	fprintf(stderr, "\n\trb <-- Receive Binary");
X#endif /* LOCAL */
X	fprintf(stderr, "\n\trt <-- Receive Text");
X	fprintf(stderr, "\n\tra <-- Receive Apple macintosh text");
X#ifdef LOCAL
X	fprintf(stderr, "\n\ts  <-- Send Binary");
X#else /* LOCAL */
X	fprintf(stderr, "\n\tsb <-- Send Binary");
X#endif /* LOCAL */
X	fprintf(stderr, "\n\tst <-- Send Text");
X	fprintf(stderr, "\n\tsa <-- Send Apple macintosh text");
X	fprintf(stderr, "\nOptions --");
X	fprintf(stderr, "\n\ty  <-- Use YMODEM Batch Mode on transmit");
X	fprintf(stderr, "\n\tm  <-- Use MODEM7 Batch Mode on transmit");
X	fprintf(stderr, "\n\tk  <-- Use 1K packets on transmit");
X#ifdef LOCAL
X	fprintf(stderr, "\n\tc  <-- Select checksum mode on receive");
X#else /* LOCAL */
X	fprintf(stderr, "\n\tc  <-- Select CRC mode on receive");
X#endif /* LOCAL */
X	fprintf(stderr, "\n\tt  <-- Indicate a TOO BUSY Unix system");
X	fprintf(stderr, "\n\td  <-- Delete xmodem.log file before starting");
X	fprintf(stderr, "\n\tl  <-- (ell) Turn OFF Log File Entries");
X	fprintf(stderr, "\n\tx  <-- Include copious debugging information in log file");
X	fprintf(stderr, "\n");
X	}
X
X/* get type of transmission requested (text or binary) */
Xgettype(ichar)
Xchar ichar;
X	{
X	if (ichar == 't' || ichar == 'T')
X		return('t');
X	else if (ichar == 'b' || ichar == 'B')
X		return('b');
X	else if (ichar == 'a' || ichar == 'A')
X		return('a');
X	else
X		error("Invalid Send/Receive Parameter - not t or b", FALSE);
X	return('\0');
X	}
X
X/* return a string containing transmission type */
Xchar *
Xprtype(ichar)
Xchar ichar;
X	{
X	if (ichar == 't' || ichar == 'T')
X		return("text");
X	else if (ichar == 'b' || ichar == 'B')
X		return("binary");
X	else if (ichar == 'a' || ichar == 'A')
X		return("apple");
X	else
X		return("");
X	}
X
X/* print error message and exit; if mode == TRUE, restore normal tty modes */
Xerror(msg, mode)
Xchar *msg;
Xint mode;
X	{
X	if (mode)
X		restoremodes(TRUE);  /* put back normal tty modes */
X	fprintf(stderr, "\r\n%s\n", msg);
X	if ((LOGFLAG || DEBUG) && (LOGFP != NULL))
X		{   
X		fprintf(LOGFP, "XMODEM Fatal Error:  %s\n", msg);
X	    	fclose(LOGFP);
X		}
X	exit(-1);
X	}
X
X
X/* Construct a proper (i.e. pretty) sector count for messages */
X
Xchar
X*sectdisp(recvsectcnt, bufsize, plus1)
Xlong recvsectcnt;
Xint bufsize, plus1;
X	{
X	static char string[20];
X	if (plus1)
X		recvsectcnt += (bufsize == 128) ? 1 : 8;
X	if (bufsize == 128 || recvsectcnt == 0)
X		sprintf (string, "%d", recvsectcnt);
X	else
X		sprintf (string, "%d-%d", recvsectcnt-7, recvsectcnt);
X	return(string);
X	}
X
X/* type out debugging info */
Xxmdebug(str)
Xchar *str;
X	{
X	if (DEBUG && (LOGFP != NULL))
X		fprintf(LOGFP,"DEBUG: '%s'\n",str);
X	}
X
X/* print elapsed time and rate of transfer in logfile */
X
Xint quant[] = { 60, 60, 24};	
Xchar sep[3][10] = { "second", "minute", "hour" };
X
Xprtime (numsect, seconds)
Xlong numsect;
Xtime_t seconds;
X
X{
X	register int i;
X	register int Seconds;
X	int nums[3];
X	int rate;
X
X	if (!LOGFLAG || numsect == 0)
X		return(0);
X
X	Seconds = (int)seconds;
X	Seconds = (Seconds > 0) ? Seconds : 0;
X
X	rate = (Seconds != 0) ? 128 * numsect/Seconds : 0;
X
X	for (i=0; i<3; i++) {
X		nums[i] = (Seconds % quant[i]);
X		Seconds /= quant[i];
X	}
X
X	fprintf (LOGFP, "%ld Sectors Transfered in ", numsect);
X
X	if (rate == 0)
X		fprintf (LOGFP, "0 seconds");
X	else
X		while (--i >= 0)
X			if (nums[i])
X				fprintf (LOGFP, "%d %s%c ", nums[i], &sep[i][0],
X					nums[i] == 1 ? ' ' : 's');
X	fprintf (LOGFP, "\n");
X
X	if (rate != 0)
X		fprintf (LOGFP, "Transfer Rate = %d Characters per Second\n", rate);
X
X	return(0);
X}
X
X/* Print elapsed time estimate */
X
Xprojtime (numsect, fd)
Xlong numsect;
XFILE *fd;
X	{
X	register int i;
X	register int seconds;
X	int nums[3];
X
X	if (numsect == 0)
X		return (0);
X
X/* constant below should really be 1280; reduced to 90% to account for time lost in overhead */
X
X	seconds = 1422 * numsect / ttyspeed + 1;
X
X	for (i=0; i<3; i++) {
X		nums[i] = (seconds % quant[i]);
X		seconds /= quant[i];
X	}
X
X	fprintf (fd, "Estimated transmission time ");
X
X	while (--i >= 0)
X		if (nums[i])
X			fprintf (fd, "%d %s%c ", nums[i], &sep[i][0],
X				nums[i] == 1 ? ' ' : 's');
X	fprintf (fd, "\n");
X	return (0);
X	}
SHAR_EOF
if test 4381 -ne "`wc -c < 'misc.c'`"
then
	echo shar: "error transmitting 'misc.c'" '(should have been 4381 characters)'
fi
fi
echo shar: "extracting 'receive.c'" '(12880 characters)'
if test -f 'receive.c'
then
	echo shar: "will not over-write existing file 'receive.c'"
else
sed 's/^X//' << \SHAR_EOF > 'receive.c'
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 */
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 */
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");
Xif (CRCMODE)
Xlogit("CRC mode requested\n");
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;
Xfilelength = 0l; fileread =0l; CHECKLENGTH = 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 (CRCMODE)        
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 || recvsectcnt > 0));
X
X	if (firstchar == EOT)           /* check for REAL EOT */
X	{
X		flushin();
X		sendbyte(NAK);              /* NAK the EOT */
X		if ((firstchar = readbyte(3)) != EOT)   /* check next character */
X		{
X			logit("Spurious EOT detected; ignored\n");
X			if ((firstchar == SOH) || (firstchar == STX) ||
X			    (firstchar == ACK && recvsectcnt == 0) ||
X			    (firstchar == CAN && recvsectcnt == 0) ||
X			    (firstchar == TIMEOUT))
X				break;
X			else
X			{
X				firstchar = 0;
X				errorflag = TRUE;
X			}
X		}
X	}
X
X	if (firstchar == TIMEOUT)       /* timeout? */
X	{  
X		if (recvsectcnt > 0)
X			logitarg("Timeout on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
X		errorflag = TRUE;
X	}
X
X	if (firstchar == CAN)           /* bailing out? (only at beginning) */
X	{
X		if ((readbyte(3) & 0x7f) == CAN)
X			error("Reception canceled at user's request",TRUE);
X		else
X		{
X			errorflag = TRUE;
X			logit("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		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 User", TRUE);
X				else
X				{
X					logit("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				return (FALSE);
X			}
X
X			if (c == TIMEOUT)
X			{
X				logit("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				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					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					errorflag = TRUE;
X				}
X			}
X			else
X			{
X				logit("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				logit("1K packet mode chosen\n");
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 %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						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								logitarg("File Name: %s\n", name);
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							flushin();          /* flush input */
X							sendbyte(ACK);      /* ACK the received packet */
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						fileread = readbackup;
X						errorflag = TRUE;
X					}
X				}
X
X				else    /* read timeout */
X				{
X					logitarg("Timeout while reading sector %s\n",sectdisp(recvsectcnt,bufsize,1));
X					fileread = readbackup;
X					errorflag = 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
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								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							sscanf(p, "%ld%lo%o", &filelength, &modtime, &filemode);
X							logitarg("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							}
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(&modtime));
X							}
X							if (filemode)
X								logitarg("YMODEM file mode: %o", filemode);
X
X							sendbyte(ACK);      /* ACK the packet */
X							firstwait = WAITFIRST;  /* reset to negotiate */
X						}
X
X						else                /* bad filename checksum */
X						{
X							logit("checksum error on filename sector\n");
X							errorflag = TRUE;
X						}
X					}
X					else
X					{
X						logit("Timeout while reading filename packet\n");
X						errorflag = TRUE;
X					}
X				}
X
X				else if (sectcurr == sectnum)   /* duplicate sector? */
X				{  
X					logitarg("Duplicate sector %s flushed\n", sectdisp(recvsectcnt,bufsize,0));
X					flushin();                  /* REALLY flush input */
X					while(readbyte(1) != TIMEOUT)
X						;
X					sendbyte(ACK);
X				}
X				else                /* no, real phase error */
X				{
X					logitarg("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			errorflag = 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(1) != TIMEOUT)  /* wait for line to settle */
X				;
X			sendbyte(NAK);
X		}
X	}
X
X	if (recvsectcnt == 0 && errorflag && firstchar != EOT) 	/* handle startup handshake */
X	{
X		sterrors++;
X
X		if (sterrors >= STERRORMAX)
X			fatalerror = TRUE;
X
X		else if (CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
X		{
X			CRCMODE = FALSE;
X			logit("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			sendbyte(CRCCHR);
X			if (LONGPACK && !MDM7BAT)
X				sendbyte(KCHR);
X		}
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	prtime (recvsectcnt, time((time_t *) 0) - start);
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		error("ABORTED -- Too Many Errors--deleting file", TRUE);
X	}
X	else if (recvsectcnt != 0)
X		error("ABORTED -- Too Many Errors", TRUE);
X	else
X		error("ABORTED -- Remote system is not responding", TRUE);
X}
Xreturn(FALSE);
X
X}
SHAR_EOF
if test 12880 -ne "`wc -c < 'receive.c'`"
then
	echo shar: "error transmitting 'receive.c'" '(should have been 12880 characters)'
fi
fi
echo shar: "extracting 'send.c'" '(9886 characters)'
if test -f 'send.c'
then
	echo shar: "will not over-write existing file 'send.c'"
else
sed 's/^X//' << \SHAR_EOF > 'send.c'
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	}
SHAR_EOF
if test 9886 -ne "`wc -c < 'send.c'`"
then
	echo shar: "error transmitting 'send.c'" '(should have been 9886 characters)'
fi
fi
echo shar: "extracting 'xmodem.c'" '(8408 characters)'
if test -f 'xmodem.c'
then
	echo shar: "will not over-write existing file 'xmodem.c'"
else
sed 's/^X//' << \SHAR_EOF > 'xmodem.c'
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 *	{ihnp4,ncar}!noao!grandi   grandi@noao.arizona.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
X	/* initialize option flags */
X
X#ifdef NOCLOBBER
X	char ans[10];
X#endif /* NOCLOBBER */
X#ifdef LOCAL
X	XMITTYPE = 'b';		/* assume binary transfer */
X#else /* LOCAL */
X	XMITTYPE = 't';		/* assume text transfer */
X#endif /* LOCAL */
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#ifdef LOCAL
X	CRCMODE = TRUE;		/* use crc-16 for now */
X#else /* LOCAL */
X	CRCMODE = FALSE;	/* use checksums for now */
X#endif /* LOCAL */
X	DELFLAG = FALSE;	/* don't delete old log file */
X#ifdef LOCAL
X	LOGFLAG = FALSE;	/* keep log */
X#else /* LOCAL */
X	LOGFLAG = TRUE;		/* keep log */
X#endif /* LOCAL */
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
X	fprintf(stderr, "XMODEM Version %d.%d", VERSION/10, VERSION%10);
X	fprintf(stderr, " -- UNIX-Microcomputer Remote 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	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#ifdef LOCAL
X		case 'c' : CRCMODE = FALSE; /* enable checksum on receive */
X#else /* LOCAL */
X		case 'c' : CRCMODE = TRUE; /* enable CRC on receive */
X#endif /* LOCAL */
X			   break;
X		case 'D' :
X		case 'd' : DELFLAG = TRUE;  /* delete log file */
X			   break;
X		case 'L' :
X#ifdef LOCAL
X		case 'l' : LOGFLAG = TRUE;  /* turn on log  */
X#else /* LOCAL */
X		case 'l' : LOGFLAG = FALSE;  /* turn off log  */
X#endif /* LOCAL */
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 'R' :
X		case 'r' : RECVFLAG = TRUE;  /* receive file */
X#ifdef LOCAL
X				if (argv[1][index] == 'b' || argv[1][index] == 'B') {
X					index++;
X					XMITTYPE = 'b';
X					break;
X				}
X				if (argv[1][index] == 't' || argv[1][index] == 'T') {
X					index++;
X					XMITTYPE = 't';
X					break;
X				}
X				if (argv[1][index] == 'a' || argv[1][index] == 'A') {
X					index++;
X					XMITTYPE = 'a';
X					break;
X				}
X#else /* LOCAL */
X			   XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
X#endif /* LOCAL */
X			   break;
X		case 'S' :
X		case 's' : SENDFLAG = TRUE;  /* send file */
X#ifdef LOCAL
X				if (argv[1][index] == 'b' || argv[1][index] == 'B') {
X					index++;
X					XMITTYPE = 'b';
X					break;
X				}
X				if (argv[1][index] == 't' || argv[1][index] == 'T') {
X					index++;
X					XMITTYPE = 't';
X					break;
X				}
X				if (argv[1][index] == 'a' || argv[1][index] == 'A') {
X					index++;
X					XMITTYPE = 'a';
X					break;
X				}
X#else /* LOCAL */
X			   XMITTYPE = gettype(argv[1][index++]);
X#endif /* LOCAL */
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("Fatal - 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("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	if (RECVFLAG && SENDFLAG)
X		error("Fatal - Both Send and Receive Functions Specified", FALSE);
X
X	if (MDM7BAT && YMDMBAT)
X		error("Fatal - Both YMODEM and MODEM7 Batch Protocols Specified", FALSE);
X
X	if (!RECVFLAG && !SENDFLAG)
X		error("Fatal - Either Send or Receive Function must be chosen!",FALSE);
X	
X	if (SENDFLAG && argc==2)
X		error("Fatal - 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 */ 
X		CRCMODE = MDM7BAT ? FALSE : TRUE;
X		fprintf(stderr, "Ready for BATCH RECEIVE");
X		fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
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#ifdef NOCLOBBER
X			while(1) {
X				printf("File exists - overwrite (y/n)? ");
X				gets(ans);
X				if (ans[0] == 'n' || ans[0] == 'N')
X					exit(0);
X				if (ans[0] == 'y' || ans[0] == 'Y')
X					break;
X			}
X#endif /* NOCLOBBER */
X			{
X			logit("Warning -- Target File Exists and is Being Overwritten\n");
X#ifndef NOCLOBBER
X			fprintf(stderr, "Warning -- Target File Exists and is Being Overwritten\n");
X#endif /* NOCLOBBER */
X			}
X		fprintf(stderr, "Ready to RECEIVE File %s", argv[2]);
X		fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
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		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			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		fprintf(stderr, "Send several Control-X characters to cancel\n");
X
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				continue;
X			}
X			sfile(argv[index]);
X		}
X		sfile("");
X		flushin();
X		restoremodes(FALSE);
X
X		logit("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		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}
SHAR_EOF
if test 8408 -ne "`wc -c < 'xmodem.c'`"
then
	echo shar: "error transmitting 'xmodem.c'" '(should have been 8408 characters)'
fi
fi
echo shar: "extracting 'xmodem.h'" '(3369 characters)'
if test -f 'xmodem.h'
then
	echo shar: "will not over-write existing file 'xmodem.h'"
else
sed 's/^X//' << \SHAR_EOF > 'xmodem.h'
X#include <ctype.h>
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#ifdef SYSV
X#include <time.h>
X#include <termio.h>
X#define rindex strrchr
X#define index strchr
X#else /* SYSV */
X#include <sys/time.h>
X#include <sgtty.h>
X#endif /* SYSV */
X#include <signal.h>
X
X/* define macros to print messages in log file */
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
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
X/*  XMODEM Constants  */
X#define      TIMEOUT  	-1
X#define      ERRORMAX  	10    /* maximum errors tolerated while transferring a packet */
X#define      WAITFIRST  1     /* seconds between startup characters in read */
X#define      STERRORMAX	60    /* maximum "errors" tolerated in read startup */
X#define      CRCSWMAX	30    /* maximum time to try CRC mode before switching */
X#define      NAKMAX	120   /* maximum times to wait for initial NAK when sending */
X#define      RETRYMAX  	5     /* maximum retries to be made certain handshaking routines */
X#define      KSWMAX	5     /* maximum errors before switching to 128 byte packets */
X#define      EOTMAX	10    /* maximum times sender will send an EOT to end transfer */
X#define      SLEEPNUM	100   /* target number of characters to collect during sleepy time */
X#define	     BBUFSIZ	1024  /* buffer size */
X#define      NAMSIZ	11    /* length of a CP/M file name string */
X#define	     CTRLZ	032   /* CP/M EOF for text (usually!) */
X#define      CRCCHR	'C'   /* CRC request character */
X#define      KCHR	'K'   /* 1K block request character */
X#define      BAD_NAME	'u'   /* Bad filename indicator */
X
X#define      CREATMODE	0644  /* mode for created files */
X
X/* GLOBAL VARIABLES */
X
Xint ttyspeed;		/* tty speed (bits per second) */
Xunsigned char buff[BBUFSIZ];	/* buffer for data */
Xint nbchr;		/* number of chars read so far for buffered read */
Xlong filelength;	/* length specified in YMODEM header */
Xlong fileread;		/* characters actually read so far in file */
Xchar filename[256];	/* place to construct filenames */
XFILE *LOGFP;		/* descriptor for LOG file */
X
X/* option flags and state variables */
Xchar	XMITTYPE;	/* text or binary? */
Xint	DEBUG;		/* keep debugging info in log? */
Xint	RECVFLAG;	/* receive? */
Xint	SENDFLAG;	/* send? */
Xint	BATCH;		/* batch? (Now used as a state variable) */
Xint	CRCMODE;	/* CRC or checksums? */
Xint	DELFLAG;	/* don't delete old log file? */
Xint	LOGFLAG;	/* keep log? */
Xint	LONGPACK; 	/* do not use long packets on transmit? */
Xint	MDM7BAT;	/* MODEM7 batch protocol */
Xint	YMDMBAT;	/* YMODEM batch protocol */
Xint	TOOBUSY;	/* turn off sleeping in packet read routine */
Xint	CHECKLENGTH;	/* Are we truncating a file to a YMODEM length? */
X
X
X/*   CRC-16 constants.  From Usenet contribution by Mark G. Mendel, 
X     Network Systems Corp.  (ihnp4!umn-cs!hyper!mark)
X*/
X
X    /* the CRC polynomial. */
X#define	P	0x1021
X
X    /* number of bits in CRC */
X#define W	16
X
X    /* the number of bits per char */
X#define B	8
SHAR_EOF
if test 3369 -ne "`wc -c < 'xmodem.h'`"
then
	echo shar: "error transmitting 'xmodem.h'" '(should have been 3369 characters)'
fi
fi
echo shar: "extracting 'xmodem.1'" '(7948 characters)'
if test -f 'xmodem.1'
then
	echo shar: "will not over-write existing file 'xmodem.1'"
else
sed 's/^X//' << \SHAR_EOF > 'xmodem.1'
X.TH XMODEM LOCAL "April 14, 1988"
X.UC 4.2
X.SH NAME
Xxmodem \- Christensen protocol file transfer utility
X.SH SYNOPSIS
X.B xmodem
X[\fBst|sb|sa|rt|rb|ra\fR][\fBymkctdlx\fR]
X[file...]
X.br
X.SH DESCRIPTION
XThe
X.I xmodem
Xprogram 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 
X.IR xmodem .
XFor details of the protocols,
Xsee the document edited by Chuck Forsberg titled
X.I
XXMODEM/YMODEM Protocol Reference.
X.sp
XOption Flags are case insensitive; the cluster of flags 
Xmay be preceded by an optional "-"
Xcharacter.
X.PP
X.SH PARAMETERS
XExactly one of the following must be selected:
X.TP
X.B rb  
XReceive Binary - files are placed on the Unix disk without conversion.
X.I Xmodem
Xwill silently destroy existing files of the same name.
X.TP
X.B rt  
XReceive Text - files are converted from the CP/M and MS-DOS
Xformat of CR-LF pairs to the Unix convention of newline 
Xcharacters only between lines.  
XNull bytes are ignored and bit 8 of each character is stripped (which makes 
XWordstar files much more readable).
XA CTRL-Z character is deemed to indicate the EOF location in the incoming
Xfile.
XThe resulting file
Xis acceptable to the Unix editors and compilers, and is usually slightly
Xsmaller than the original file.
X.I Xmodem
Xwill silently destroy existing files of the same name.
X.TP
X.B ra
XReceive Apple - same as rt save CR characters in the incoming file are 
Xtranslated into Unix newline characters.
X.TP
X.B sb  
XSend Binary - files are sent without conversion as they exist on the Unix disk.
X.TP
X.B st  
XSend Text - newline characters in the file are converted to CR-LF pairs
Xin accord with the CP/M and MS-DOS conventions for text files.  The file
X"grows" in this process.
X.TP
X.B sa  
XSend Apple - same as st save newline characters are converted into CR
Xcharacters in accord with Apple Macintosh conventions for text files.
X.PP
X.SH OPTIONS
X.TP
X.B y
XSelect the YMODEM batch protocol for sending files; a list of files specified
Xon the command line will be sent in sequence.  The YMODEM batch protocol is 
Xused automatically for file reception if the sending program requests it.
XIf this flag is specified for a batch receive, (\fIxmodem rty\fR, for example),
Xthe transfer will never attempt to switch from CRC to checksum mode.
X.TP
X.B m
XSelect the MODEM7 batch protocol for sending files; a list of files specified
Xon the command line will be sent in sequence.  The MODEM7 batch protocol is 
Xused automatically for file reception if the sending program requests it.
XIf this flag is specified for a batch receive, (\fIxmodem rbm\fR, for example),
Xthe transfer starts in checksum mode rather than CRC mode.
X.TP
X.B k
XSelect the XMODEM-1K file transfer mode for sending files. Use of 1K packets on
Xlow-error lines increases throughput.  
XHowever, over direct connections at 9600 bps to a busy host, 1K packets may
Xcause data overflows generating excessive retries.
X1K packets are automatically
Xused for file reception if the sending program requests it.
XIf this flag is specified with the YMODEM flag in a batch receive (\fIxmodem
Xrbyk\fR, for example), the program will attempt to use the "KMD/IMP" convention
Xto invoke 1K file transfers.
X.TP
X.B c   
XSelect the CRC-16 error-checking protocol on receive.  CRC mode is better at catching
Xtransmission errors that occur than the alternative checksum protocol.  
XCRC mode is automatically selected for file
Xtransmission if the receiving modem program requests it.
X.TP
X.B t
XIndicates the Unix system is Too Busy and 
X.I xmodem
Xshould fall back to a simpler I/O strategy than normal.
X.TP
X.B d   
XDelete the 
X.I xmodem.log
Xfile before file transfer is begun.
X.TP
X.B l   
XDo NOT write to the log file.  If logging is selected, a file
X.I xmodem.log 
Xwill be created (or appended to), with entries for significant events, errors
Xand retries.  This can be useful to see why things went wrong
Xwhen they do.
X.TP
X.B x
XToggle on debug mode.  If debug mode is selected, copious and possibly
Xuseful debugging information will be placed in 
X.IR xmodem.log .
X.SH "FILE NAMES"
XFiles transmitted using one of the batch modes
Xwill be stored on the remote machine under a CP/M-ified name (path names
Xstripped, limited
Xto eight characters plus a three character extension; ":" characters will
Xbe turned into "/" characters; all characters will be in monocase).  
XFiles received using one of the batch modes
Xwill be stored under their transmitted names (except that any "/" characters
Xin the file name will be converted into ":" characters, all upper-case
Xcharacters will be translated into lower case and trailing dots will be
Xexpunged).
X.PP
XWhen a batch receive is requested,
X.I xmodem
Xtakes a wait and see attitude and can adapt to either batch protocol or even
Xa classic XMODEM transfer (note that CRC-16 mode is automatically set under
Xthese circumstances unless the b flag is specified).
XIf a classic, "non-batch" XMODEM file reception takes place, 
Xthe received file is stored as
X.IR xmodem.in .
XFile names present on the command line for a batch receive are ignored.
X.SH NOTES
XWhile waiting for the beginning of a file transfer, 
X.I xmodem
Xtreats two CAN (CTRL-X) characters that are received within 3 seconds
Xas a request to abort.  CAN characters will not cause an abort if received
Xduring a file transfer.
X.PP
XIf 10 or more errors are detected during the transmission or reception of any
Xone packet, the transfer is aborted.
X.PP
XSqueezed, compressed or ARCed files must be transferred in binary mode, even if they
Xcontain text.
X.PP
XIf you use 
X.I xmodem
Xover a 
X.I rlogin
Xlink, you may have to use the form
X.IR "rlogin machine -8" .
X.PP
XIf an unexpected error occurs before a file is completely received, the
Xincomplete file is deleted.
X.PP
XFiles received using both binary and text mode in a YMODEM batch transfer 
Xwill be truncated
Xto the file size specified in the YMODEM header (extra CR characters in the
Xincoming file are correctly handled).  File sizes are included in
Xthe YMODEM header when sending both binary and text files.  Thus files
Xtransferred via YMODEM should preserve their exact length.
XFile modification times are set for received files if present in the YMODEM
Xheader; they are included in the headers for transmitted files.
X.PP
XThe "KMD/IMP" record count field in the YMODEM header is both set and read.
X.SH EXAMPLES
XTo receive a text file transmitted from a micro (using CRC-16
Xerror-checking) and store it under the
Xname 
X.IR file.name ,
Xuse the command line
X.RS
X.B "xmodem rtc file.name"
X.RE
XNote that if the transmitting program on the micro uses the 1K packet
Xprotocol or either batch protocol,
X.I xmodem
Xdetects this automatically and takes appropriate action.  Further
Xnote that if one of the batch protocols is used, the received file(s)
Xwill be stored under their own names and the name on the command line
X(if any) will be ignored.
X.PP
XTo send a set of text files to a microcomputer using 1K packets and the
XYMODEM batch protocol, use the command line
X.RS
X.B "xmodem styk *.txt"
X.RE
X.SH FILES
Xxmodem.log (if logging is enabled)
X.SH BUGS
XBatch mode could be smarter about bad file-names in the midst of a
Xbatch transmit/receive.
X.PP
XBatch mode could allow a mixture of binary and text files.
X.PP
XBare Carriage Return characters (i.e., those not immediately followed by a
XLine Feed character) are mishandled in a received file when using text mode.
XA file with ``overstruck'' lines will thus come out looking funny.
X.PP
XYMODEM header packets are only sent as 128 byte packets.  Thus VERY long file
Xnames will not be handled properly.
X.SH SEE ALSO
Xkermit(1)
X.SH AUTHOR
XSteve Grandi, National Optical Astronomy Observatories.  Based on
X.I xmodem
Xby Brian Kantor, University of California at San Diego.
XThis, in turn, was based on
X.I umodem
Xby Lauren Weinstein, Richard Conn and others.
SHAR_EOF
if test 7948 -ne "`wc -c < 'xmodem.1'`"
then
	echo shar: "error transmitting 'xmodem.1'" '(should have been 7948 characters)'
fi
fi
exit 0
#	End of shell archive

egray@fthood.UUCP (07/15/88)

This part 3 of 3 to Steve Grandi's xmodem v3.6 package.

Emmet P. Gray				US Army, HQ III Corps & Fort Hood
...!uunet!uiucuxc!fthood!egray		Attn: AFZF-DE-ENV
					Directorate of Engineering & Housing
					Environmental Management Office
					Fort Hood, TX 76544-5057

------------------------------------------------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	xmodem.l
#	tip.diffs
#	update.doc
# This archive created: Thu Jul 14 13:12:51 1988
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'xmodem.l'" '(8026 characters)'
if test -f 'xmodem.l'
then
	echo shar: "will not over-write existing file 'xmodem.l'"
else
sed 's/^X//' << \SHAR_EOF > 'xmodem.l'
X.TH XMODEM 1 net
X.SH NAME
Xxmodem \- Christensen protocol file transfer utility
X.SH SYNOPSIS
X.B xmodem
X[\fBr\fR|\fBrt\fR|\fBra\fR|\fBs\fR|\fBst\fR|\fBsa\fR][\fBymkctdlx\fR]
X[file...]
X.br
X.SH DESCRIPTION
XThe
X.I xmodem
Xprogram implements the Christensen (XMODEM) file transfer
Xprotocol for moving files between 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 
X.IR xmodem .
XFor details of the protocols,
Xsee the document edited by Chuck Forsberg titled
X.I
XXMODEM/YMODEM Protocol Reference.
X.sp
XOption Flags are case insensitive; the cluster of flags 
Xmay be preceded by an optional "-"
Xcharacter.
X.PP
X.SH PARAMETERS
XExactly one of the following must be selected:
X.TP
X.B r
XReceive Binary - files are placed on the Unix disk without conversion.
XIf a batch protocol is not specified
X.I xmodem
Xwill prompt the user before overwriting an existing file of the same name.
XBatch protocols avoid file name collisions by prepending the letter 'X' to
Xthe file name.
X.TP
X.B rt  
XReceive Text - files are converted from the CP/M and MS-DOS
Xformat of CR-LF pairs to the Unix convention of newline 
Xcharacters only between lines.  
XNull bytes are ignored and bit 8 of each character is stripped (which makes 
XWordstar files much more readable).
XA CTRL-Z character is deemed to indicate the EOF location in the incoming
Xfile.
XThe resulting file
Xis acceptable to the Unix editors and compilers, and is usually slightly
Xsmaller than the original file.
X.TP
X.B ra
XReceive Apple - same as rt save CR characters in the incoming file are 
Xtranslated into Unix newline characters.
X.TP
X.B s
XSend Binary - files are sent without conversion as they exist on the Unix disk.
X.TP
X.B st  
XSend Text - newline characters in the file are converted to CR-LF pairs
Xin accord with the CP/M and MS-DOS conventions for text files.  The file
X"grows" in this process.
X.TP
X.B sa  
XSend Apple - same as st save newline characters are converted into CR
Xcharacters in accord with Apple Macintosh conventions for text files.
X.PP
X.SH OPTIONS
X.TP
X.B y
XSelect the YMODEM batch protocol for sending files; a list of files specified
Xon the command line will be sent in sequence.  The YMODEM batch protocol is 
Xused automatically for file reception if the sending program requests it.
XIf this flag is specified for a batch receive, (\fIxmodem rty\fR, for example),
Xthe transfer will never attempt to switch from CRC to checksum mode.
X.TP
X.B m
XSelect the MODEM7 batch protocol for sending files; a list of files specified
Xon the command line will be sent in sequence.  The MODEM7 batch protocol is 
Xused automatically for file reception if the sending program requests it.
XIf this flag is specified for a batch receive, (\fIxmodem rmc\fR, for example),
Xthe transfer starts in checksum mode rather than CRC mode.
X.TP
X.B k
XSelect the XMODEM-1K file transfer mode for sending files. Use of 1K packets on
Xlow-error lines increases throughput.  
XHowever, over direct connections at 9600 bps to a busy host, 1K packets may
Xcause data overflows generating excessive retries.
X1K packets are automatically
Xused for file reception if the sending program requests it.
XIf this flag is specified with the YMODEM flag in a batch receive (\fIxmodem
Xryk\fR, for example), the program will attempt to use the "KMD/IMP" convention
Xto invoke 1K file transfers.
X.TP
X.B c   
XSelect the checksum error-checking protocol on receive.  Although the CRC
Xmode is better at catching
Xtransmission errors than the checksum method, older systems may not use CRC.  
XCRC mode is automatically selected for file
Xtransmission if the receiving modem program requests it.
X.TP
X.B t
XIndicates the Unix system is Too Busy and 
X.I xmodem
Xshould fall back to a simpler I/O strategy than normal.
X.TP
X.B d   
XDelete the 
X.I xmodem.log
Xfile before file transfer is begun.
X.TP
X.B l   
XUse logging feature.  If logging is selected, a file
X.I xmodem.log 
Xwill be created (or appended to), with entries for significant events, errors
Xand retries.  This can be useful to see why things went wrong
Xwhen they do.
X.TP
X.B x
XToggle on debug mode.  If debug mode is selected, copious and possibly
Xuseful debugging information will be placed in 
X.IR xmodem.log .
X.SH "FILE NAMES"
XFiles transmitted using one of the batch modes
Xwill be stored on the remote machine under a CP/M-ified name (path names
Xstripped, limited
Xto eight characters plus a three character extension; ":" characters will
Xbe turned into "/" characters; all characters will be in monocase).  
XFiles received using one of the batch modes
Xwill be stored under their transmitted names (except that any "/" characters
Xin the file name will be converted into ":" characters, all upper-case
Xcharacters will be translated into lower case and trailing dots will be
Xexpunged).
X.PP
XWhen a batch receive is requested,
X.I xmodem
Xtakes a wait and see attitude and can adapt to either batch protocol or even
Xa classic XMODEM transfer (note that CRC-16 mode is automatically set under
Xthese circumstances unless the c flag is specified).
XIf a classic, "non-batch" XMODEM file reception takes place, 
Xthe received file is stored as
X.IR xmodem.in .
XFile names present on the command line for a batch receive are ignored.
X.SH NOTES
XWhile waiting for the beginning of a file transfer, 
X.I xmodem
Xtreats two CAN (CTRL-X) characters that are received within 3 seconds
Xas a request to abort.  CAN characters will not cause an abort if received
Xduring a file transfer.
X.PP
XIf 10 or more errors are detected during the transmission or reception of any
Xone packet, the transfer is aborted.
X.PP
XSqueezed, compressed or ARCed files must be transferred in binary mode, even if they
Xcontain text.
X.PP
XIf you use 
X.I xmodem
Xover a 
X.I rlogin
Xlink, you may have to use the form
X.IR "rlogin machine -8" .
X.PP
XIf an unexpected error occurs before a file is completely received, the
Xincomplete file is deleted.
X.PP
XFiles received using both binary and text mode in a YMODEM batch transfer 
Xwill be truncated
Xto the file size specified in the YMODEM header (extra CR characters in the
Xincoming file are correctly handled).  File sizes are included in
Xthe YMODEM header when sending both binary and text files.  Thus files
Xtransferred via YMODEM should preserve their exact length.
XFile modification times are set for received files if present in the YMODEM
Xheader; they are included in the headers for transmitted files.
X.PP
XThe "KMD/IMP" record count field in the YMODEM header is both set and read.
X.SH EXAMPLES
XTo receive a text file transmitted from a micro (using CRC-16
Xerror-checking) and store it under the
Xname 
X.IR file.name ,
Xuse the command line
X.RS
X.B "xmodem rt file.name"
X.RE
XNote that if the transmitting program on the micro uses the 1K packet
Xprotocol or either batch protocol,
X.I xmodem
Xdetects this automatically and takes appropriate action.  Further
Xnote that if one of the batch protocols is used, the received file(s)
Xwill be stored under their own names and the name on the command line
X(if any) will be ignored.
X.PP
XTo send a set of text files to a microcomputer using 1K packets and the
XYMODEM batch protocol, use the command line
X.RS
X.B "xmodem styk *.txt"
X.RE
X.SH FILES
Xxmodem.log (if logging is enabled)
X.SH BUGS
XBatch mode could be smarter about bad file-names in the midst of a
Xbatch transmit/receive.
X.PP
XBatch mode could allow a mixture of binary and text files.
X.PP
XBare Carriage Return characters (i.e., those not immediately followed by a
XLine Feed character) are mishandled in a received file when using text mode.
XA file with ``overstruck'' lines will thus come out looking funny.
X.PP
XYMODEM header packets are only sent as 128 byte packets.  Thus VERY long file
Xnames will not be handled properly.
X.SH SEE ALSO
Xkermit(1)
X.SH AUTHOR
XSteve Grandi, National Optical Astronomy Observatories.  Based on
X.I xmodem
Xby Brian Kantor, University of California at San Diego.
XThis, in turn, was based on
X.I umodem
Xby Lauren Weinstein, Richard Conn and others.
SHAR_EOF
if test 8026 -ne "`wc -c < 'xmodem.l'`"
then
	echo shar: "error transmitting 'xmodem.l'" '(should have been 8026 characters)'
fi
fi
echo shar: "extracting 'tip.diffs'" '(14301 characters)'
if test -f 'tip.diffs'
then
	echo shar: "will not over-write existing file 'tip.diffs'"
else
sed 's/^X//' << \SHAR_EOF > 'tip.diffs'
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  }
SHAR_EOF
if test 14301 -ne "`wc -c < 'tip.diffs'`"
then
	echo shar: "error transmitting 'tip.diffs'" '(should have been 14301 characters)'
fi
fi
echo shar: "extracting 'update.doc'" '(9209 characters)'
if test -f 'update.doc'
then
	echo shar: "will not over-write existing file 'update.doc'"
else
sed 's/^X//' << \SHAR_EOF > 'update.doc'
XChanges leading to version 3.3
X
X1) "Better" handshaking for MODEM7 batch transfers (5/19/87).
X
X2) If reception of a file is aborted due to errors, delete incomplete file
X(5/19/87).
X
X3) If an "impossible" tty speed is detected, assume 1200 bps (5/19/87).
X
X4) Disallow CAN-CAN abort during file send or receive except at beginning of
Xfile transfer (during batch transfers, CAN-CAN abort is allowed at beginning
Xof each file transfer) (5/19/87).
X
X5) Uncouple total allowed errors during the reception of a single packet 
X(ERRORMAX, now made 10) and errors allowed when starting transfer (STERRORMAX, 
Xset to 10) (5/19/87).
X
X6) Fix some bugs when receiving an empty file and when a phase error occurs
Xduring a file reception (5/19/87).
X
X7) Portability fix in prtime and projtime; they also handle pathological
Xcases better (5/19/87).
X
X8) During file reception an EOT is not believed unless it is sent again in
Xresponse to a NAK (5/25/87).
X
X9) Modified cpm_unix and unixify so a filename without an extension will not
Xhave a trailing dot in its filename after being received in a MODEM7 or
XYMODEM batch transfer (5/25/87).
X
X10) Allowable errors during transmission of a single packet now set to
XERRORMAX (5/27/87).
X
X11) When transferring a binary file, the YMODEM file length field is filled
Xin on transmit and (if present) used to truncate the file on reception.
XA new truncate function (truncfile) added to getput.c to do the deed (5/28/87).
XThe file mode field is also set but is ignored on file reception.
X
X12) In a batch receive (xmodem -rt), program can be forced into checksum mode
Xby specifying the "M" flag indicating a MODEM7 transfer (5/30/87).
X
X13) Changed the "B" option to "M" to indicate MODEM7 batch.  Made all option
Xflags case insensitive.  Command line is now recorded in the log file
X(5/30/87).
X
X14) The "KND/IMP" convention of using "CK" to invoke 1K packets during YMODEM
Xbatch transfers was installed.  This code will be sent during a batch receive 
Xif "K" is included on the command line unless "M" is also present.  This code
Xwill be recognized when sending under all circumstances (5/30/87).
X
X------------------------------------------------------------------------------
X
XChanges leading to version 3.4
X
X1) Fix usage message (10/2/87).
X
X2) Sender will now try up to 10 times (EOTMAX) to send an EOT to terminate a
Xtransmission.  Used to be 5 times, but Chuck Forsberg's "official" minimum
Xrequirements for YMODEM mandate 10 (10/2/87).
X
X3) Handle YMODEM file modification times if present in header on reception of
Xboth binary and text files (10/2/87).  Retracted when can't seem to get
Xproper times whn playing with dsz (10/3/87).  Found bug and reinstalled
Xfeature (10/16/87).  Found REAL bug (10/21/87).
X
X4) Null bytes are now stripped out of files when received as text files (MEX
Xdoesn't seem to want to put in the terminating control-Z) (10/3/87).
X
X5) Slightly modified terminal parameter setting to explicitly turn of CRMOD
Xand to flush read queue; ideas stolen from Kermit.  Will it fly on Pyramid?
X(10/3/87).
X
X6) Decreased time between "startup" characters sent when starting a file
Xreceive operation.  This should increase perceived response.  Now waits 
XWAITFIRST seconds (set to 1) instead of 6 (waits for 5 seconds for 
Xsubsequent packets.  STERRORMAX now 60, CRCSWMAX now 30.  
XTimeouts on 1st sector no longer reported in log (10/5/87).
X
X7) Once again played with kernel sleeps in readbuf() (packet reading
Xroutine).  On busy system could cause real problems.  Now supply flag (t) to
Xsuppress sleeping on Too Busy systems.  No longer suppress sleep when speeds are
Xover 4800 bps.  Sleep kludge DOES help: on an empty 750 running 4.3BSD, a
Xfile reception at 2400 bps used 6% of the CPU with the sleep kludge and 24%
Xwithout it (data transfer rates were the the same) (10/5/87).
X
X8) Actually count characters as they are being read for a file reception.
XWhen YMODEM file length is set, stop writing characters when reach length.
XThis will allow YMODEM file lengths to work for text files and the
Xelimination of truncfile() in getput.c (which was impossible for SYS V)
X(10/5/87).
X
X9) Another attempt at tty modes.  Now do nothing but set speeds, set mode to
Xraw, and turn off echoing and tandem (10/6/87).
X
X------------------------------------------------------------------------------
X
XChanges leading to version 3.5
X
X1) Following the suggestion of Bill Carpenter (ho5cad!wjc), I changed every
Xprintf("") to fprintf(stderr, "") so one can use xmodem on either end of unix
Xto unix link. (3/24/88).
X
X2) Again, thanks to Bill Carpenter, corrected typo in stamptime() in
Xgetput.sysv.c (3/24/88).
X
X3) Thanks to Steve Lebowitz (prcpto!pdvshl), fixed a && that should have been
Xa & in getput.sysv.c (3/25/88).
X
X4) Thanks to Leo Pilachowski, who managed to fool xmodem by "preplacing" ACKS
Xin the VAX's input queue (improves throughput by 20%, says Leo, but makes
Xerror recovery a tad dicey...!).  Implemented a flushin() function in
Xgetput.c to flush any pending characters.  flushin is called in send.c just
Xafter sending a packet to make sure a proper ACK or NAK is received (I hope 
Xfast machines don't beat me to it and get their ACKS flushed!).  In
Xreceive.c, flushin is called prior to the "startup" characters, prior to
Xsending the packet acknowledgment ACK and prior to the NAK prompting for
Xconfirming EOT.  Now how does one implement flushin() on Sys V? (3/25/88).
X
X5) Fixed pair of bugs in send.c:  YMODEM test enforcing CRC was testing
Xnumber of attempts against STERRORMAX instead of ERRORMAX (also shortened
Xtimeout interval on this read) and a "timeout" during packet send was not
Xnoticed (due to a > instead of a >=) thus program started sending EOTs which
Xfurther delayed abort (3/28/88).
X
X6) Modified send.c and cpmify function in batch.c to strip path names on file
Xnames transmitted as part of YMODEM batch (3/28/88).
X
X7) Hacked receive.c to make end of loop processing clearer and improve
Xgarbage flushing when errors are detected (3/28/88).
X
X8) Pulled out of decision restricting YMODEM batch send to use CRC only.  Will 
Xnow gladly use checksum if told to and will respond to NAK as well as the 
Xproper C when starting up data transfer (3/28/88).  Turns out this patch fixes 
Xproblem with Red Ryder (4/10/88).
X
X9) Tested MODEM7 batch against MEX-PC.  Confirmation of EOT during filename
Xtransmission was not working, so xmodem wasn't shutting down a MODEM7 batch
Xreceive.  Removed code to NAK first EOT and wait for second EOT (3/28/88).
X
X10) Added code to count number of newlines in a text file to get an accurate
Xfile size.  I thought it would take too long; but seems to be quite nimble
X(see countnl in getput.c).  We now transmit YMODEM file length and mode
Xinformation for text as well as binary files (3/29/88).
X
X11) After a YMODEM file name packet was received, forgot to reset "wait" time
Xfor receiving first character of data packet which definitely slowed
Xperceived performance.  (See note 6 for v. 3.4).  Fixed (4/7/88).
X
X------------------------------------------------------------------------------
X
XChanges leading to version 3.6
X
X1) Added two new major commands (sa and ra) to send and receive text files
Xfor Apple Macintoshs which use CR as EOL character instead of the MS/DOS CR
XLF pair.  Thanks to Dave Nowak (djnowak@iseesun.DPL.SCG.HAC.COM) for the
Xinspiration (4/11/88).
X
X2) Experiences with Red Ryder 10.3.  Fixed botch in receive.c that led to an
Xinfinite loop when a checksum failed on YMODEM file name packet.  Now have
Xseperate variables for packet errors and "startup" errors.  Prevent CRC to
Xchecksum switch during receive startup if YMDMBAT flag is true.  This insures
Xthat no such transition will ever take place on second or subsequent file
Xtransfer; can be set on first file by including Y option on command line.  No
Xlonger print "0" expected sectors if both YMODEM file length and KMD file
Xlength are both 0 (4/12/88).
X
X3) Cleaned up ifs in readbuf.  Removed void declaration on flushin (will
Xbreak 4.2BSD compiler?).  Corrected "number of sent sectors" on YMODEM
Xtransfer (was counting filename packet) (4/12/88).
X
X4) More experiences with Red Ryder.  Removed line flush before every CRCCHR
Xor NAK trying to start a receive (RR YMODEM batch send to the VAX now seems
Xto work).  Fixed KMD "1K reception flag" to work properly on a receive. 
XAdded a flushin just before program exits in a futile effort to eliminate
XRR's nasty habit of sending a final EOT down the line.  Reaaranged
Xvariables in send.c so longpackets requested by the KMD flag are not
X"sticky" from file to file in a batch.  RR is a real DOG: ony gets about 133
Xcps when downloading to a Mac over a 9600 bps line! (4/14/88). 
X
X------------------------------------------------------------------------------
X
XThanks to Keith Peterson (w8sdz@simtel20.arpa), John Rupley
X(arizona!rupley!root), Emmet Gray (ihnp4!uiucuxc!fthood!egray), Bob Bickford
X(lll-crg!well!rab), Doug Moore (moore@svax.cs.cornell.edu), David Brown
X(jdb@ncsc.arpa), Bill Carpenter (ho5cad!wjc), Steve Lebowitz (prcpto!pdvshl),
XLeo Pilachowski, Dave Nowak (djnowak@iseesun.DPL.SCG.HAC.COM) and Chuck
XForsberg's documents and his ZCOMM/DSZ/rz/sz programs for ideas, suggestions
Xand comments. 
SHAR_EOF
if test 9209 -ne "`wc -c < 'update.doc'`"
then
	echo shar: "error transmitting 'update.doc'" '(should have been 9209 characters)'
fi
fi
exit 0
#	End of shell archive

egray@fthood.UUCP (07/15/88)

Hello netlanders!

Here is Steve Grandi's xmodem version 3.6.  (I've once again taken the
stand that cross posting source from comp.source.* to unix-pc.source is
justified and generally a good idea.)

I've made a few changes to suit my tastes, but did it in such a way that
you can choose the flavor of xmodem by editing the Makefile.  There is a
Readme.local file that describes the changes I've made.

Emmet P. Gray				US Army, HQ III Corps & Fort Hood
...!uunet!uiucuxc!fthood!egray		Attn: AFZF-DE-ENV
					Directorate of Engineering & Housing
					Environmental Management Office
					Fort Hood, TX 76544-5057

-----------------------------------------------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	Header
#	README
#	Readme.local
#	Makefile
#	batch.c
#	getput.bsd.c
#	getput.c
#	getput.sysv.c
# This archive created: Thu Jul 14 13:12:40 1988
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'Header'" '(1427 characters)'
if test -f 'Header'
then
	echo shar: "will not over-write existing file 'Header'"
else
sed 's/^X//' << \SHAR_EOF > 'Header'
XSubmitted-by: Steve Grandi <grandi@noao.arizona.edu>
XPosting-number: Volume 15, Issue 70
XArchive-name: xmodem3.6/part01
X
X
XHere is version 3.6 of my Unix "full-featured" xmodem program.  It
Xincorporates fixes and enhancements from people who used it when it was
Xlast posted in March.  Since that version was posted with missing pieces,
XI'm submitting this version rather quickly so the "archives" will have a
Xcomplete version.
X
XAfter unpacking, you should have the following files:
X
X-rw-r--r--  1 grandi        933 Apr 14 15:01 Makefile
X-rw-r--r--  1 grandi       4367 Apr 14 07:56 README
X-rw-r--r--  1 grandi       4735 Mar 28 15:25 batch.c
X-rw-r--r--  1 grandi      12045 Apr 14 06:57 getput.c
X-rw-r--r--  1 grandi      10898 Apr 13 10:37 getput.sysv.c
X-rw-r--r--  1 grandi       4076 Apr 11 08:59 misc.c
X-rw-r--r--  1 grandi      12880 Apr 14 07:15 receive.c
X-rw-r--r--  1 grandi       9886 Apr 14 10:07 send.c
X-rw-r--r--  1 grandi      14301 Jan  7 14:30 tip.diffs
X-rw-r--r--  1 grandi       9209 Apr 14 09:41 update.doc
X-rw-r--r--  1 grandi       7948 Apr 14 07:53 xmodem.1
X-rw-r--r--  1 grandi       6834 Apr 14 07:19 xmodem.c
X-rw-r--r--  1 grandi       3240 Apr 11 07:39 xmodem.h
X
XSteve Grandi, National Optical Astronomy Observatories, Tucson AZ, 602-325-9228
XUUCP: {arizona,decvax,ncar,ihnp4}!noao!grandi or uunet!noao.arizona.edu!grandi
XInternet: grandi@noao.arizona.edu    SPAN/HEPNET: 5355::GRANDI or NOAO::GRANDI
X
X
SHAR_EOF
if test 1427 -ne "`wc -c < 'Header'`"
then
	echo shar: "error transmitting 'Header'" '(should have been 1427 characters)'
fi
fi
echo shar: "extracting 'README'" '(4367 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
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
XTo answer one oft-asked question: No, I don't know how to tie this
Xfull-featured xmodem program into tip or cu for file transfers when calling
Xout from a 4.3BSD system.  4.3BSD tip does have some undocumented hooks
Xfor tying into other programs through redirecting file descriptors, but my
Xminimal attempts to utilize these hooks have failed.  However, several
Xyears back, I built a VERY early version of xmodem (lacking XMODEM/CRC,
XXMODEM-1K, MODEM7 batch or YMODEM) directly into 4.2BSD tip.  The changes
Xworked unmodified in 4.3BSD; the diff files are contained in the file
Xtip.diffs.
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 8-4-87).
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
X--------------------------------------------------------------------------------
X
XProgram 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 
Xfor what follows....)
X
XVersion 2.0 (CRC-16 and Modem7 batch file transfer) (5/85)
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
X--------------------------------------------------------------------------------
X
XPlease send bug fixes, additions and comments to:
XSteve Grandi, National Optical Astronomy Observatories (Tucson, Arizona)
X	{ihnp4,ncar,arizona,...}!noao!grandi  grandi@noao.arizona.edu
SHAR_EOF
if test 4367 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 4367 characters)'
fi
fi
echo shar: "extracting 'Readme.local'" '(1035 characters)'
if test -f 'Readme.local'
then
	echo shar: "will not over-write existing file 'Readme.local'"
else
sed 's/^X//' << \SHAR_EOF > 'Readme.local'
XHello netlanders!
X
XThis is Steve Grandi's xmodem version 3.6 with a few enhancements and
Xlocal modifications.  You can pick and choose the flavor of xmodem
Xyou want by editing the Makefile preprocessor definitons:
X
X	SYSV		Compile for AT&T Unix system V and friends.
X
X	NOCLOBBER	If not a batch protocol, prompt the user before
X			overwriting an existing file.  If batch, create
X			unique names.
X
X	LOCAL		Change a bunch of default settings:
X
X			1) binary xfers assumed, 'b' option is optional.
X			2) CRC is assumed, 'c' option is now for checksum
X			3) loging defaults to off, 'l' turns it on.
X
XThe manual page with a lower case 'l' is edited to reflect the NOCLOBBER
Xand LOCAL options.
X
XFor users of the AT&T Unix PC 7300/3b1, there is a line in the Makefile
Xthat will allow the program to be compiled with shared libraries.
X
XEmmet P. Gray				US Army, HQ III Corps & Fort Hood
X...!uunet!uiucuxc!fthood!egray		Attn: AFZF-DE-ENV
X					Directorate of Engineering & Housing
X					Environmental Management Office
X					Fort Hood, TX 76544-5057
SHAR_EOF
if test 1035 -ne "`wc -c < 'Readme.local'`"
then
	echo shar: "error transmitting 'Readme.local'" '(should have been 1035 characters)'
fi
fi
echo shar: "extracting 'Makefile'" '(1141 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
XOBJECTS = xmodem.o getput.o misc.o send.o receive.o batch.o
XLDFLAGS = -s
X#CFLAGS = -O
X# see the Readme.local file for what these do.
XCFLAGS = -O -DSYSV -DNOCLOBBER -DLOCAL
X
Xxmodem: $(OBJECTS)
X# for users of AT&T Unix PC 7300/3b1
X	$(LD) $(LDFLAGS) $(OBJECTS) /lib/crt0s.o /lib/shlib.ifile -o xmodem
X#	cc $(LDFLAGS) $(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 update.doc Makefile xmodem.1 xmodem.h > xmodem.shar.1
X	shar xmodem.c receive.c misc.c > xmodem.shar.2
X	shar getput.c getput.sysv.c > xmodem.shar.3
X	shar batch.c send.c > xmodem.shar.4
X	shar tip.diffs > 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 tip.diffs > 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	tip.diffs ymodem.doc
X	compress xmodem.tar
SHAR_EOF
if test 1141 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 1141 characters)'
fi
fi
echo shar: "extracting 'batch.c'" '(5485 characters)'
if test -f 'batch.c'
then
	echo shar: "will not over-write existing file 'batch.c'"
else
sed 's/^X//' << \SHAR_EOF > 'batch.c'
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#ifdef NOCLOBBER
X	chg_name(name);
X#endif /* NOCLOBBER */
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#ifdef NOCLOBBER
X	chg_name(filename);
X#endif /* NOCLOBBER */
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}
X
X#ifdef NOCLOBBER
X/*
X * Handle file name collisions.  Prepend an 'X' to the name until you find
X * a name that doesn't already exist.
X */
X
Xchg_name(str)
Xchar *str;
X{
X	register int i;
X	char temp[15], ans[15], *s, *rindex(), *strcpy(), *strncat();
X
X					/* dissect the name component */
X	if ((s = rindex(str, '/')))
X		strcpy(temp, s++);
X	else
X		strcpy(temp, str);
X
X	strcpy(ans, temp);
X					/* prepend up to 13 'X's */
X	for (i=1; i<14; i++) {
X		if (access(ans, 0)) {
X			strcpy(str, ans);
X			return(0);
X		}
X
X		strcpy(temp, "X");
X		strncat(temp, ans, 13);
X		temp[14] = NULL;
X		strcpy(ans, temp);
X	}
X	return(-1);
X}
X#endif /* NOCLOBBER */
SHAR_EOF
if test 5485 -ne "`wc -c < 'batch.c'`"
then
	echo shar: "error transmitting 'batch.c'" '(should have been 5485 characters)'
fi
fi
echo shar: "extracting 'getput.bsd.c'" '(12045 characters)'
if test -f 'getput.bsd.c'
then
	echo shar: "will not over-write existing file 'getput.bsd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getput.bsd.c'
X/*
X * Contains system routines to get and put bytes, change tty modes, etc
X * Most of the routines are VERY 4.2BSD Specific!!!
X */
X
X#include "xmodem.h"
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 */
Xgetbyte(fildes, ch)				/* Buffered disk read */
Xint fildes;
Xchar *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			error("File Read Error", TRUE);
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		{
X		return(EOF);
X		}
X	}
X
X/* Count the number of newlines in a file so we know the REAL file size */
X
Xlong
Xcountnl(fd)
Xint fd;
X{
X	char buf[BUFSIZ];
X	char *bufp;
X	long nltot = 0;
X	int numchar;
X	long lseek();
X
X	while (numchar = read(fd, buf, BUFSIZ))		/* cycle through file */
X		for (bufp=buf; numchar--; bufp++)
X			if (*bufp == '\n')
X				nltot++;
X
X	(void) lseek (fd, 0l, 0);			/* rewind file */
X	if (DEBUG)
X		fprintf(LOGFP, "DEBUG: countnl--%ld newlines counted\n", nltot);
X	return (nltot);
X}
X
X/*   CRC-16 constant array...
X     from Usenet contribution by Mark G. Mendel, Network Systems Corp.
X     (ihnp4!umn-cs!hyper!mark)
X*/
X
X/* crctab as calculated by initcrctab() */
Xunsigned short crctab[1<<B] = { 
X    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
X    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
X    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
X    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
X    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
X    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
X    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
X    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
X    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
X    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
X    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
X    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
X    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
X    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
X    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
X    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
X    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
X    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
X    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
X    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
X    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
X    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
X    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
X    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
X    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
X    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
X    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
X    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
X    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
X    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
X    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
X    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
X    };
X
X/* get a byte from data stream -- timeout if "seconds" elapses */
X/* This routine is VERY 4.2 specific */
X
Xint
Xreadbyte(seconds)
Xint seconds;
X	{
X	int readfd;
X	char c;
X	struct timeval tmout;
X
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
X	return(c & 0xff);  /* return the char */
X	}
X
X/* flush input stream by reading pending characters */
X
Xflushin()
X	{
X	int readfd;
X	char inbuf[BBUFSIZ];
X	struct timeval tmout;
X
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
X/* 
X get a buffer (length bufsize) from data stream -- timeout if "seconds" elapses.
X Read bunches of characters to save system overhead;
X Further process data while kernel is reading stream (calculating "checksum").
X Try to nap long enough so kernel collects 100 characters or so until we wake up
X unless TOOBUSY is set.
X*/
X
X/* This routine is VERY 4.2 specific */
X
Xint
Xreadbuf(bufsize, seconds, tmode, amode, recvsectcnt, checksum, bufctr)
X
Xint bufsize,	/* number of chars to be read */
Xseconds, 	/* timeout period for each read */
Xtmode, 		/* transmission mode: TRUE if text */
Xamode, 		/* transmission mode: TRUE if apple macintosh */
X*checksum, 	/* pointer to checksum value */
X*bufctr;	/* length of actual data string in buffer */
Xlong 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	int j;			/* loop index */
X	char *sectdisp();
X
X	tmout.tv_sec = seconds;
X	tmout.tv_usec = 0;
X	readfd = 1<<0;
X	chksm = 0;
X	bfctr = 0;
X
X	for (left = bufsize; left > 0;) {
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			fprintf(LOGFP, "DEBUG: readbuf--read %d characters\n", numread);
X
X		/* now process part of packet we just read */
X
X		for (j =  0; j < numread; j++) 
X			{  
X				buff[bfctr] = c = inbuf[j] & 0xff;
X				fileread++;
X
X				if (CRCMODE)  /* CRC */
X					chksm = (chksm<<B) ^ crctab[(chksm>>(W-B)) ^ c];
X
X				else        /* checksum */
X		       			chksm = ((chksm+c) & 0xff);
X
X				if (CHECKLENGTH && fileread > filelength)	/* past EOF ? */
X					continue;
X
X				if (tmode) 		/* text mode processing */
X					{
X					buff[bfctr] &= 0x7f;	/* nuke bit 8 */
X					if (c == CR || c == 0)	/* skip CRs and nulls */
X						continue;
X					else if (c == CTRLZ)	/* CP/M EOF char */
X						{  
X						recfin = TRUE;
X		       				continue;
X		       				}
X		       			else if (!recfin)	/* don't increment if past EOF */
X						bfctr++;
X					}
X				else if (amode) 	/* Apple macintosh text mode processing */
X					{
X					buff[bfctr] &= 0x7f;	/* nuke bit 8 */
X					if (c == 0)		/* skip nulls */
X						continue;
X					else if (c == CR)	/* translate CR to LF */
X						buff[bfctr] = LF;
X					else if (c == CTRLZ)	/* CP/M EOF char */
X						{  
X						recfin = TRUE;
X		       				continue;
X		       				}
X		       			if (!recfin)		/* don't increment if past EOF */
X						bfctr++;
X					}
X				else			/* binary */
X					bfctr++;
X
X		     	}	
X
X		/* go to sleep to save uneeded system calls while kernel
X		   is reading data from serial line; 
X		   fudge constant from 10000 to 9000 to avoid sleeping too long.
X		*/
X		if (left && !TOOBUSY)
X		    napms( (left<SLEEPNUM ? left:SLEEPNUM) * 9000/ttyspeed);
X
X	}
X
X	if (CHECKLENGTH && fileread >= filelength)
X		logitarg("File end from YMODEM length found in sector %s\n",
X		  sectdisp(recvsectcnt,bufsize,1));
X	*checksum = chksm;
X	*bufctr = bfctr;
X	return(0);
X}
X
X/* send a byte to data stream */
X
Xsendbyte(data)
Xchar data;
X	{
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
X/* send a buffer to data stream */
X
Xwritebuf(buffer, nbytes)
Xchar *buffer;
Xint  nbytes;
X	{
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
X/*
X * "nap" for specified time -- VERY 4.2BSD specific
X */
X
Xnapms (milliseconds)
Xint	milliseconds;
X{
X	struct	timeval	timeout;
X	int readfd;
X
X	if (milliseconds == 0)
X		return;
X	if (DEBUG)
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
X 
X/* set and restore tty modes for XMODEM transfers */
X/* These routines are 4.2/v7(?) specific */
X
Xstruct sgttyb ttys, ttysnew;	/* for stty terminal mode calls */
Xstruct stat statbuf;		/* for terminal message on/off control */
X
Xint wason;			/* holds status of tty read write/modes */
Xchar *tty;			/* current tty name */
X
X
Xsetmodes()
X	{
X	char *ttyname();
X
X	int n;
X
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	ttysnew.sg_flags |= RAW;	/* set for RAW Mode */
X	ttysnew.sg_flags &= ~ECHO;	/* set for no echoing */
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	if (stat(tty, &statbuf) < 0)  
X		error("Can't get your TTY Status", TRUE);
X
X	if (statbuf.st_mode & 022)	/* Need to turn messages off */
X		if (chmod(tty, (int)statbuf.st_mode & ~022) < 0)
X			error("Can't change  TTY mode", TRUE);
X		else 
X			wason = TRUE;
X	else 
X		wason = FALSE;
X
X	/* set up signal catcher to restore tty state if we are KILLed */
X
X	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
X		signal(SIGTERM, onintr);
X	}
X
X/* restore normal tty modes */
X
Xrestoremodes(errcall)
Xint errcall;
X	{
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		     printf("RESET - Can't restore normal TTY Params\n");
X		}
X	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
X		signal(SIGTERM, SIG_DFL);
X	return;
X	}
X
X
X
X
X/* signal catcher */
Xonintr()
X	{
X	error("Kill signal; bailing out", TRUE);
X	}
X
X/* create string with a timestamp for log file */
X
Xchar *stamptime()
X{
X	char *asctime();		/* stuff to get timestamp */
X	struct tm *localtime(), *tp;
X	struct timeval tv;
X	struct timezone tz;
X
X	gettimeofday (&tv, &tz);		/* fill in timestamp */
X	tp = localtime ((time_t *)&tv.tv_sec);
X	return(asctime(tp));
X}
X
X
X
X/* get tty speed for time estimates */
X
Xgetspeed()
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		{
X		ttyspeed = speedtbl[ttys.sg_ispeed];
X		logitarg ("Line speed = %d bits per second\n", ttyspeed);
X		}
X	else
X		{
X		ttyspeed = 1200;
X		logit ("Can't determine line speed; assuming 1200 bps\n");
X		}
X	}
SHAR_EOF
if test 12045 -ne "`wc -c < 'getput.bsd.c'`"
then
	echo shar: "error transmitting 'getput.bsd.c'" '(should have been 12045 characters)'
fi
fi
echo shar: "extracting 'getput.c'" '(10863 characters)'
if test -f 'getput.c'
then
	echo shar: "will not over-write existing file 'getput.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getput.c'
X/*
X * Contains system routines to get and put bytes, change tty modes, etc
X * Sys V version.  UNTESTED!!!!!!
X */
X
X#include "xmodem.h"
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 */
Xgetbyte(fildes, ch)				/* Buffered disk read */
Xint fildes;
Xchar *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			error("File Read Error", TRUE);
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		{
X		return(EOF);
X		}
X	}
X
X/* Count the number of newlines in a file so we know the REAL file size */
X
Xlong
Xcountnl(fd)
Xint fd;
X{
X	char buf[BUFSIZ];
X	char *bufp;
X	long nltot = 0;
X	int numchar;
X	long lseek();
X
X	while (numchar = read(fd, buf, BUFSIZ))		/* cycle through file */
X		for (bufp=buf; numchar--; bufp++)
X			if (*bufp == '\n')
X				nltot++;
X
X	(void) lseek (fd, 0l, 0);			/* rewind file */
X	if (DEBUG)
X		fprintf(LOGFP, "DEBUG: countnl--%ld newlines counted\n", nltot);
X	return (nltot);
X}
X
X/*   CRC-16 constant array...
X     from Usenet contribution by Mark G. Mendel, Network Systems Corp.
X     (ihnp4!umn-cs!hyper!mark)
X*/
X
X/* crctab as calculated by initcrctab() */
Xunsigned short crctab[1<<B] = { 
X    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
X    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
X    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
X    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
X    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
X    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
X    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
X    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
X    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
X    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
X    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
X    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
X    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
X    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
X    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
X    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
X    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
X    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
X    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
X    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
X    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
X    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
X    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
X    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
X    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
X    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
X    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
X    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
X    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
X    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
X    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
X    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
X    };
X
X/* get a byte from data stream -- timeout if "seconds" elapses */
X
Xint timedout;
X 
Xint
Xreadbyte(seconds)
Xint seconds;
X{
X	int force_it();
X	char c;
X	signal(SIGALRM, force_it);
X
X	timedout = 0;
X	alarm(seconds);
X	read(0, &c, 1);
X	alarm(0);
X	if (timedout)
X		return(TIMEOUT);
X	if (DEBUG)
X		fprintf(LOGFP, "DEBUG: readbyte %02xh\n", c & 0xff);
X	return(c & 0xff);
X}
X
Xint
Xforce_it()
X{
X	timedout++;
X	return;
X}
X
X
X/* flush input stream */
X
Xflushin()
X	{
X/* No good way to do this without select */
X/* Perhaps....but we waste 1 second with every call!
X	while (readbyte(1) != TIMEOUT)
X		;
X*/
X	}
X
X/* 
X get a buffer (length bufsize) from data stream -- timeout if "seconds" elapses.
X Read bunches of characters to save system overhead;
X Further process data while kernel is reading stream (calculating "checksum").
X Try to nap long enough so kernel collects 100 characters or so until we wake up
X unless TOOBUSY is set.
X*/
X
X
Xint
Xreadbuf(bufsize, seconds, tmode, amode, recvsectcnt, checksum, bufctr)
X
Xint bufsize,	/* number of chars to be read */
Xseconds, 	/* timeout period for each read */
Xtmode, 		/* transmission mode: TRUE if text */
Xamode, 		/* transmission mode: TRUE if apple macintosh */
X*checksum, 	/* pointer to checksum value */
X*bufctr;	/* length of actual data string in buffer */
Xlong recvsectcnt;	/* running sector count (128 byte sectors) */
X
X{
X	int force_it();
X	int numread;		/* number of chars read */
X	int left;		/* number of chars left to read */
X	int recfin = 0;		/* 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	int j;			/* loop index */
X	char *sectdisp();
X
X	signal(SIGALRM, force_it);
X	chksm = 0;
X	bfctr = 0;
X
X	for (left = bufsize; left > 0;) {
X
X		/* read however many chars are waiting */
X		timedout = 0;
X		alarm(seconds);
X		numread = read(0, inbuf, left);
X		alarm(0);
X		if (timedout)
X			return(TIMEOUT);
X		left -= numread;
X
X		if (DEBUG)
X			fprintf(LOGFP, "DEBUG: readbuf--read %d characters\n", numread);
X
X		/* now process part of packet we just read */
X
X		for (j =  0; j < numread; j++) 
X			{  
X				buff[bfctr] = c = inbuf[j] & 0xff;
X				fileread++;
X
X				if (CRCMODE)  /* CRC */
X					chksm = (chksm<<B) ^ crctab[(chksm>>(W-B)) ^ c];
X
X				else        /* checksum */
X		       			chksm = ((chksm+c) & 0xff);
X
X				if (CHECKLENGTH && fileread > filelength)	/* past EOF ? */
X					continue;
X
X				if (tmode) 		/* text mode processing */
X					{
X					buff[bfctr] &= 0x7f;	/* nuke bit 8 */
X					if (c == CR || c == 0)	/* skip CRs and nulls */
X						continue;
X					else if (c == CTRLZ)	/* CP/M EOF char */
X						{  
X						recfin = TRUE;
X		       				continue;
X		       				}
X		       			else if (!recfin)	/* don't increment if past EOF */
X						bfctr++;
X					}
X				else if (amode) 	/* Apple macintosh text mode processing */
X					{
X					buff[bfctr] &= 0x7f;	/* nuke bit 8 */
X					if (c == 0)		/* skip nulls */
X						continue;
X					else if (c == CR)	/* translate CR to LF */
X						buff[bfctr] = LF;
X					else if (c == CTRLZ)	/* CP/M EOF char */
X						{  
X						recfin = TRUE;
X		       				continue;
X		       				}
X		       			if (!recfin)	/* don't increment if past EOF */
X						bfctr++;
X					}
X				else			/* binary */
X					bfctr++;
X
X		     	}	
X
X		/* go to sleep to save uneeded system calls while kernel
X		   is reading data from serial line, fudge constant from 10 to
X		   9 to avoid sleeping too long
X		*/
X		if (left && !TOOBUSY)
X			sleep ((left<SLEEPNUM ? left:SLEEPNUM) * 9/ttyspeed);
X	}
X
X	if (CHECKLENGTH && fileread >= filelength)
X		logitarg("File end from YMODEM length found in sector %s\n",
X		  sectdisp(recvsectcnt,bufsize,1));
X	*checksum = chksm;
X	*bufctr = bfctr;
X	return(0);
X}
X
X/* send a byte to data stream */
X
Xsendbyte(data)
Xchar data;
X	{
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
X/* send a buffer to data stream */
X
Xwritebuf(buffer, nbytes)
Xchar *buffer;
Xint  nbytes;
X	{
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
X/* set and restore tty modes for XMODEM transfers */
X
Xstruct termio ttys;
Xstruct stat statbuf;		/* for terminal message on/off control */
X
Xint wason;			/* holds status of tty read write/modes */
Xchar *tty;			/* current tty name */
X
X
Xsetmodes()
X	{
X	char *ttyname();
X	struct termio ttysnew;
X
X	extern onintr();
X
X	sleep(2);			/* let the output appear */
X	if (ioctl(0,TCGETA,&ttys)<0)  /* get tty params */
X		error("Can't get TTY Parameters", TRUE);
X
X	tty = ttyname(0);  /* identify current tty */
X	
X	if (ioctl(0,TCGETA,&ttysnew)<0)  /* get tty params */
X		error("Can't get TTY Parameters", TRUE);
X	ttysnew.c_cc[4] = 1;		/* VMIN */
X	ttysnew.c_cc[5] = 0;		/* VTIME */
X	ttysnew.c_iflag = 0;
X	ttysnew.c_oflag = 0;
X	ttysnew.c_lflag = 0;
X	ttysnew.c_cflag &= ~CSIZE;
X	ttysnew.c_cflag |= CS8;
X	ttysnew.c_cflag &= ~PARENB;
X	if (ioctl(0,TCSETA,&ttysnew)<0)  /* set new paramters */
X		error("Can't set new TTY Parameters", TRUE);
X
X	if (stat(tty, &statbuf) < 0)  /* get tty status */ 
X		error("Can't get your TTY Status", TRUE);
X
X	if (statbuf.st_mode & 022)	/* Need to turn messages off */
X		if (chmod(tty, (int)statbuf.st_mode & ~022) < 0)
X			error("Can't change  TTY mode", TRUE);
X		else 
X			wason = TRUE;
X	else 
X		wason = FALSE;
X
X	/* set up signal catcher to restore tty state if we are KILLed */
X
X	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
X		signal(SIGTERM, onintr);
X	}
X
X/* restore normal tty modes */
X
Xrestoremodes(errcall)
Xint errcall;
X	{
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,TCSETA,&ttys) < 0)
X		{ if (!errcall)
X		   error("RESET - Can't restore normal TTY Params", FALSE);
X		else
X		     printf("RESET - Can't restore normal TTY Params\n");
X		}
X	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
X		signal(SIGTERM, SIG_DFL);
X	return;
X	}
X
X
X
X
X/* signal catcher */
Xonintr()
X	{
X	error("Kill signal; bailing out", TRUE);
X	}
X
X/* create string with a timestamp for log file */
X
Xchar *stamptime()
X{
X	char *asctime();		/* stuff to get timestamp */
X	struct tm *localtime(), *tp;
X	long now;
X
X	time(&now);
X	tp = localtime(&now);
X	return(asctime(tp));
X}
X
X
X
X/* get tty speed for time estimates */
X
Xgetspeed()
X	{
X	static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
X	1200, 1800, 2400, 4800, 9600, 19200, 0};
X	struct termio ttystemp;
X
X	if (ioctl(0,TCGETA,&ttystemp) < 0)	/* get tty structure */
X		error("Can't get TTY parameters", FALSE);
X	if ((ttystemp.c_cflag & 017)<=14)
X		{
X		ttyspeed = speedtbl[ttystemp.c_cflag & 017];
X		logitarg ("Line speed = %d bits per second\n", ttyspeed);
X		}
X	else
X		{
X		ttyspeed = 1200;
X		logit ("Can't determine line speed; assuming 1200 bps\n");
X		}
X	}
SHAR_EOF
if test 10863 -ne "`wc -c < 'getput.c'`"
then
	echo shar: "error transmitting 'getput.c'" '(should have been 10863 characters)'
fi
fi
echo shar: "extracting 'getput.sysv.c'" '(10863 characters)'
if test -f 'getput.sysv.c'
then
	echo shar: "will not over-write existing file 'getput.sysv.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getput.sysv.c'
X/*
X * Contains system routines to get and put bytes, change tty modes, etc
X * Sys V version.  UNTESTED!!!!!!
X */
X
X#include "xmodem.h"
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 */
Xgetbyte(fildes, ch)				/* Buffered disk read */
Xint fildes;
Xchar *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			error("File Read Error", TRUE);
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		{
X		return(EOF);
X		}
X	}
X
X/* Count the number of newlines in a file so we know the REAL file size */
X
Xlong
Xcountnl(fd)
Xint fd;
X{
X	char buf[BUFSIZ];
X	char *bufp;
X	long nltot = 0;
X	int numchar;
X	long lseek();
X
X	while (numchar = read(fd, buf, BUFSIZ))		/* cycle through file */
X		for (bufp=buf; numchar--; bufp++)
X			if (*bufp == '\n')
X				nltot++;
X
X	(void) lseek (fd, 0l, 0);			/* rewind file */
X	if (DEBUG)
X		fprintf(LOGFP, "DEBUG: countnl--%ld newlines counted\n", nltot);
X	return (nltot);
X}
X
X/*   CRC-16 constant array...
X     from Usenet contribution by Mark G. Mendel, Network Systems Corp.
X     (ihnp4!umn-cs!hyper!mark)
X*/
X
X/* crctab as calculated by initcrctab() */
Xunsigned short crctab[1<<B] = { 
X    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
X    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
X    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
X    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
X    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
X    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
X    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
X    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
X    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
X    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
X    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
X    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
X    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
X    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
X    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
X    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
X    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
X    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
X    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
X    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
X    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
X    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
X    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
X    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
X    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
X    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
X    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
X    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
X    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
X    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
X    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
X    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
X    };
X
X/* get a byte from data stream -- timeout if "seconds" elapses */
X
Xint timedout;
X 
Xint
Xreadbyte(seconds)
Xint seconds;
X{
X	int force_it();
X	char c;
X	signal(SIGALRM, force_it);
X
X	timedout = 0;
X	alarm(seconds);
X	read(0, &c, 1);
X	alarm(0);
X	if (timedout)
X		return(TIMEOUT);
X	if (DEBUG)
X		fprintf(LOGFP, "DEBUG: readbyte %02xh\n", c & 0xff);
X	return(c & 0xff);
X}
X
Xint
Xforce_it()
X{
X	timedout++;
X	return;
X}
X
X
X/* flush input stream */
X
Xflushin()
X	{
X/* No good way to do this without select */
X/* Perhaps....but we waste 1 second with every call!
X	while (readbyte(1) != TIMEOUT)
X		;
X*/
X	}
X
X/* 
X get a buffer (length bufsize) from data stream -- timeout if "seconds" elapses.
X Read bunches of characters to save system overhead;
X Further process data while kernel is reading stream (calculating "checksum").
X Try to nap long enough so kernel collects 100 characters or so until we wake up
X unless TOOBUSY is set.
X*/
X
X
Xint
Xreadbuf(bufsize, seconds, tmode, amode, recvsectcnt, checksum, bufctr)
X
Xint bufsize,	/* number of chars to be read */
Xseconds, 	/* timeout period for each read */
Xtmode, 		/* transmission mode: TRUE if text */
Xamode, 		/* transmission mode: TRUE if apple macintosh */
X*checksum, 	/* pointer to checksum value */
X*bufctr;	/* length of actual data string in buffer */
Xlong recvsectcnt;	/* running sector count (128 byte sectors) */
X
X{
X	int force_it();
X	int numread;		/* number of chars read */
X	int left;		/* number of chars left to read */
X	int recfin = 0;		/* 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	int j;			/* loop index */
X	char *sectdisp();
X
X	signal(SIGALRM, force_it);
X	chksm = 0;
X	bfctr = 0;
X
X	for (left = bufsize; left > 0;) {
X
X		/* read however many chars are waiting */
X		timedout = 0;
X		alarm(seconds);
X		numread = read(0, inbuf, left);
X		alarm(0);
X		if (timedout)
X			return(TIMEOUT);
X		left -= numread;
X
X		if (DEBUG)
X			fprintf(LOGFP, "DEBUG: readbuf--read %d characters\n", numread);
X
X		/* now process part of packet we just read */
X
X		for (j =  0; j < numread; j++) 
X			{  
X				buff[bfctr] = c = inbuf[j] & 0xff;
X				fileread++;
X
X				if (CRCMODE)  /* CRC */
X					chksm = (chksm<<B) ^ crctab[(chksm>>(W-B)) ^ c];
X
X				else        /* checksum */
X		       			chksm = ((chksm+c) & 0xff);
X
X				if (CHECKLENGTH && fileread > filelength)	/* past EOF ? */
X					continue;
X
X				if (tmode) 		/* text mode processing */
X					{
X					buff[bfctr] &= 0x7f;	/* nuke bit 8 */
X					if (c == CR || c == 0)	/* skip CRs and nulls */
X						continue;
X					else if (c == CTRLZ)	/* CP/M EOF char */
X						{  
X						recfin = TRUE;
X		       				continue;
X		       				}
X		       			else if (!recfin)	/* don't increment if past EOF */
X						bfctr++;
X					}
X				else if (amode) 	/* Apple macintosh text mode processing */
X					{
X					buff[bfctr] &= 0x7f;	/* nuke bit 8 */
X					if (c == 0)		/* skip nulls */
X						continue;
X					else if (c == CR)	/* translate CR to LF */
X						buff[bfctr] = LF;
X					else if (c == CTRLZ)	/* CP/M EOF char */
X						{  
X						recfin = TRUE;
X		       				continue;
X		       				}
X		       			if (!recfin)	/* don't increment if past EOF */
X						bfctr++;
X					}
X				else			/* binary */
X					bfctr++;
X
X		     	}	
X
X		/* go to sleep to save uneeded system calls while kernel
X		   is reading data from serial line, fudge constant from 10 to
X		   9 to avoid sleeping too long
X		*/
X		if (left && !TOOBUSY)
X			sleep ((left<SLEEPNUM ? left:SLEEPNUM) * 9/ttyspeed);
X	}
X
X	if (CHECKLENGTH && fileread >= filelength)
X		logitarg("File end from YMODEM length found in sector %s\n",
X		  sectdisp(recvsectcnt,bufsize,1));
X	*checksum = chksm;
X	*bufctr = bfctr;
X	return(0);
X}
X
X/* send a byte to data stream */
X
Xsendbyte(data)
Xchar data;
X	{
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
X/* send a buffer to data stream */
X
Xwritebuf(buffer, nbytes)
Xchar *buffer;
Xint  nbytes;
X	{
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
X/* set and restore tty modes for XMODEM transfers */
X
Xstruct termio ttys;
Xstruct stat statbuf;		/* for terminal message on/off control */
X
Xint wason;			/* holds status of tty read write/modes */
Xchar *tty;			/* current tty name */
X
X
Xsetmodes()
X	{
X	char *ttyname();
X	struct termio ttysnew;
X
X	extern onintr();
X
X	sleep(2);			/* let the output appear */
X	if (ioctl(0,TCGETA,&ttys)<0)  /* get tty params */
X		error("Can't get TTY Parameters", TRUE);
X
X	tty = ttyname(0);  /* identify current tty */
X	
X	if (ioctl(0,TCGETA,&ttysnew)<0)  /* get tty params */
X		error("Can't get TTY Parameters", TRUE);
X	ttysnew.c_cc[4] = 1;		/* VMIN */
X	ttysnew.c_cc[5] = 0;		/* VTIME */
X	ttysnew.c_iflag = 0;
X	ttysnew.c_oflag = 0;
X	ttysnew.c_lflag = 0;
X	ttysnew.c_cflag &= ~CSIZE;
X	ttysnew.c_cflag |= CS8;
X	ttysnew.c_cflag &= ~PARENB;
X	if (ioctl(0,TCSETA,&ttysnew)<0)  /* set new paramters */
X		error("Can't set new TTY Parameters", TRUE);
X
X	if (stat(tty, &statbuf) < 0)  /* get tty status */ 
X		error("Can't get your TTY Status", TRUE);
X
X	if (statbuf.st_mode & 022)	/* Need to turn messages off */
X		if (chmod(tty, (int)statbuf.st_mode & ~022) < 0)
X			error("Can't change  TTY mode", TRUE);
X		else 
X			wason = TRUE;
X	else 
X		wason = FALSE;
X
X	/* set up signal catcher to restore tty state if we are KILLed */
X
X	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
X		signal(SIGTERM, onintr);
X	}
X
X/* restore normal tty modes */
X
Xrestoremodes(errcall)
Xint errcall;
X	{
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,TCSETA,&ttys) < 0)
X		{ if (!errcall)
X		   error("RESET - Can't restore normal TTY Params", FALSE);
X		else
X		     printf("RESET - Can't restore normal TTY Params\n");
X		}
X	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
X		signal(SIGTERM, SIG_DFL);
X	return;
X	}
X
X
X
X
X/* signal catcher */
Xonintr()
X	{
X	error("Kill signal; bailing out", TRUE);
X	}
X
X/* create string with a timestamp for log file */
X
Xchar *stamptime()
X{
X	char *asctime();		/* stuff to get timestamp */
X	struct tm *localtime(), *tp;
X	long now;
X
X	time(&now);
X	tp = localtime(&now);
X	return(asctime(tp));
X}
X
X
X
X/* get tty speed for time estimates */
X
Xgetspeed()
X	{
X	static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
X	1200, 1800, 2400, 4800, 9600, 19200, 0};
X	struct termio ttystemp;
X
X	if (ioctl(0,TCGETA,&ttystemp) < 0)	/* get tty structure */
X		error("Can't get TTY parameters", FALSE);
X	if ((ttystemp.c_cflag & 017)<=14)
X		{
X		ttyspeed = speedtbl[ttystemp.c_cflag & 017];
X		logitarg ("Line speed = %d bits per second\n", ttyspeed);
X		}
X	else
X		{
X		ttyspeed = 1200;
X		logit ("Can't determine line speed; assuming 1200 bps\n");
X		}
X	}
SHAR_EOF
if test 10863 -ne "`wc -c < 'getput.sysv.c'`"
then
	echo shar: "error transmitting 'getput.sysv.c'" '(should have been 10863 characters)'
fi
fi
exit 0
#	End of shell archive