char soh = 0x01;
char eot = 0x04;
char ack = 0x06;
char nak = 0x15;
char can = 0x18;
#include "stdio.h"
#include "signal.h"
#include "termio.h"
#include "sys/ioctl.h"
struct termio save;
struct termio new;

int lfproc = 0;
int debug = 0;
FILE *errors;
main(argc, argv)
int argc;
char **argv;
{
	int i,j;
	char buf[130];
	char blocknum = 1;
	char c_blocknum = 254;
	int numread;
	char cksum;
	char inch;
	int alarmfn();
	int kleenex();
	FILE *fp;
	extern char *optarg;
	extern int optind;
	char file[128];

	ioctl(1, TCGETA, &save);
	ioctl(1, TCGETA, &new);
	while ((i = getopt(argc, argv, "ltd")) != EOF)
		switch(i) {
		case 'd':
			debug++;
			break;
		case 'l':
		case 't':	/* TEXT file */
			lfproc++;
			break;
		case '?':
			fprintf(stderr, "Usage: %s [-d] file\n", argv[0]);
			kleenex(0);
			break;
		}
	if (debug) errors = fopen("xr.err", "w");
	if (debug && errors == NULL) {
		fprintf(stderr, "Unable to open xr.err for error tracing\n");
		kleenex(1);
	}
	if (debug) setbuf(errors, NULL);
	if (argc == 1 || argc == optind) {
		fprintf(stderr, "Need file name\n");
		kleenex(0);
	}
	strcpy(file, argv[optind]);
	for (i=1; i<20;i++) signal(i, SIG_IGN);
	signal(14, alarmfn);
	signal(3, kleenex);
	signal(1,kleenex);
	if ((fp=fopen(file, "w")) == NULL) {
		fprintf(stderr, "File not writeable: %s\n", file);
		kleenex(0);
	}
	printf("File '%s' ready for to be received.......\n", file);
	printf("Type ^X to exit, xtrans ignores signals\n");
	fflush(stdin);
	new.c_iflag = IGNBRK|IGNPAR;
	new.c_oflag = 0;
	new.c_lflag = 0;
	new.c_cc[4] = 1;
	new.c_cflag &= ~PARENB;
	new.c_cflag |= CS8;
	ioctl(1, TCSETAW, &new);
	sleep(10);
	write(1, &nak, 1);
	while (1) {
TOP:
		i = get_x_char(10, &inch);
		if (i == -1) {
			if (debug) fprintf(errors, "Timeout on block %d during SOH\n",blocknum);
			purge_send(nak);
			continue;
		}
		if (inch == can) {
			if (debug) fprintf(errors, "CAN received at block %d\n", blocknum);
			kleenex(0);
		}
		if (inch == eot) {
			if (debug) fprintf(errors, "EOT received at block %d\n", blocknum);
			break;
		}
		if (inch != soh) {
			if (debug) fprintf(errors, "Bad SOH on block %d\n",blocknum);
			purge_send(nak);
			continue;
		}
		i = get_x_char(10, &inch);
		if (i == -1 ) {
			if (debug) fprintf(errors, "Timeout on block %d during blocknum\n",blocknum);
			purge_send(nak);
			continue;
		}
		if (inch != blocknum) {
			if (debug) fprintf(errors, "Bad blocknum on block %d, expected %d, got %d\n",blocknum,blocknum,i);
			purge_send(nak);
			continue;
		}
		i = get_x_char(10, &inch);
		if (i == -1 ) {
			if (debug) fprintf(errors, "Timeout on block %d during c_blocknum\n",blocknum);
			purge_send(nak);
			continue;
		}
		if (inch != c_blocknum) {
			if (debug) fprintf(errors, "Bad c_blocknum on block %d, expected %d, got %d\n",blocknum,c_blocknum,
			    i);
			purge_send(nak);
			continue;
		}
		for (i=0;i<128;i++) {
			j = get_x_char(10, &inch);
			if (j == -1) {
				if (debug) fprintf(errors, "Timeout during block %d, during data recv, on char %d\n", blocknum,
				    i);
				purge_send(nak);
				goto TOP; /* AUGGH, a GOTO. horrendous */
			}
			buf[i] = inch;
		}
		cksum = 0;
		for (i=0;i<128;i++) {
			cksum = cksum + buf[i];
			/*if (debug) fprintf(errors,"Added %d to checksum, now %d\n",j,cksum);*/
		}
		cksum = cksum % 256;
		i = get_x_char(10, &inch);
		if (i == -1 ) {
			if (debug) fprintf(errors, "Timeout on block %d during checksum\n",blocknum);
			purge_send(nak);
			continue;
		}
		if (cksum != inch) {
			if (debug) fprintf(errors, "Bad checksum on block %d, expected %d, got %d\n",blocknum,cksum,i);
			purge_send(nak);
			continue;
		}
		if (debug) fprintf(errors, "Validated block %d\n",blocknum);
		write(1, &ack, 1);
		{int iput;
		 static int eot_flag = 0;
		 iput=128;	/* assume full buffer */
		 if (lfproc){
		     iput=0;	
		     for (i=0;i<128;i++){
			 if (buf[i] == 26){	/* MS-DOS eot */
			     eot_flag = 1;  /* 1st stage */
			     break;
			 }
			 if (buf[i] != 13) buf[iput++] = buf[i];
		     }
		 }
		 if (eot_flag < 2){
		     fwrite(buf,iput,1,fp);
		     if (eot_flag == 1) eot_flag=2; /* 2nd stage */
		 }
		}
		blocknum = (blocknum+1) % 256;
		c_blocknum = 255 - blocknum;
	}
	write(1, &ack, 1);
	kleenex(0);
}
kleenex(x)
int x;
{
	ioctl(1, TCSETA, &save);
	if (debug) fprintf(errors, "Caught signal %d\n", x);
	exit(x);
}
alarmfn() {
	signal(14, alarmfn);
}
read_in(fp, buf, num)
FILE *fp;
char *buf;
int num;
{
	int i;
	int c;
	static int cr_held = 0;

	i = 0;
	if (cr_held) {
		buf[i] = '\r';
		i++;
		cr_held = 0;
	}
	for(   ;i < num;i++) {
		c = getc(fp);
		if (c == EOF) {
			return(i);
		}
		if (c == '\n' && lfproc) {
			buf[i] = c;
			if (i == 127) {
				cr_held = 1;
				return(128);
			}
			buf[i+1] = '\r';
			i++;
		}
		else {
			buf[i] = c;
		}
	}
	return(i);
}
clear_inq() {
	int j;
	char ch;

	signal(14, alarmfn);
	do {
		j = get_x_char(2, &ch);
		/*if (debug) fprintf(errors, "cleared line of %d\n", j);*/
	} while (j > -1);
}
get_x_char(timeout, cp)
int timeout;
char *cp;
{
	int ch;
	extern int errno;
	int ret;

	alarm(timeout);
	if ((ch=getchar()) == EOF) {
		/*if (debug) fprintf(errors, "get_x_char returning read error\n");*/
		/*if (debug) fprintf(errors, "Errno == %d\n", errno);*/
		return(-1);
	}
	alarm(0);
	*cp = ch;
	return( ch );
}
purge_send(ch)
char ch;
{
	int j;
	char cp;
	/*if (debug) fprintf(errors, "Begin purge_send(%d)\n", ch);*/
	do {
		j = get_x_char(2, &cp);
	} while (j != -1);
	write(1, &ch, 1);
	/*if (debug) fprintf(errors, "End purge_send(%d)\n", ch);*/
}
                                                                                                                    