
#include "k.h"
/*
 *	s e n d s w
 *
 * sendsw is the state tabel swticher for sending files.  It loops
 * until either it is finished or an error is encountered.  The
 * routines called by sensw are responsible for changing the state.
 */

sendsw()
{

	state = 'S';		/* Send initiate is the start state */
	numtry = 0;		/* Say no tries yet */
	gnxtfl();
#if debug
	fprintf(stderr,"sendsw -- sending %s\n",filestr);
#endif
	while(TRUE)		/* Do this as long as necessary */
	{
#if debug
		fprintf(stderr,"sendsw -- state is now %c\n",state);
#endif
		switch(state)
		{
			case 'D':	state = sdata();	/* Data-Send state */
						break;

			case 'F':	state = sfile();	/* File-Send */
						break;

			case 'Z':	state = seof();		/* End-of-File */
						break;

			case 'S':	state = sinit();	/* Send-Init */
						break;

			case 'B':	state = sbreak();	/* Break-Send */
						break;

			case 'C':	return (TRUE);		/* Complete */

			case 'A':	return (FALSE);		/* Abort */
				default:	return (FALSE);		/* Unknown, abort */
		}
	}
}

/*
 *	s i n i t
 */

sinit()
{
	int num, len;

	if (numtry++ > MAXTRY)		/* If too many tries, abort */
		return('A');
	spar(packet);				/* Fill up with init info */
	spack('S',n,6,packet);		/* Send an 'S' packet */


	switch(rpack(&len,&num,recpkt))		/* What was the reply? */
	{
		case 'N':				/* NAK */
			/* if (n != num--) */

				return(state);	/* If NAK for next pack its like ACK */

		case 'Y':				/* ACK */
		{
			if (n != num)		/* If wrong ACK, fail */
				return(state);
			rpar(recpkt);		/* Get the init info */
			if (eol == 0)		/* check and set defaults */
				eol = '\n';
			if (quote == 0)
				quote = '#';
			numtry = 0;			/* reset try counter */
			n = (n+1)%64;		/* and bump packet count */
			fd = open(filestr,0);	/* Open the file to read */
			return('F');		/* switch state to F */
		}

		
		case FALSE:				/* Receive failure, fail */
			return(state);

		default:				/* Just abort */
			return('A');
	}
}


/*
 *	s f i l e
 */

sfile()
{
	int num, len;

	if (numtry++ > MAXTRY)		/* If too many tries, abort */
		return('A');
	for (len=0; filestr[len] != '\0'; len++);	/* count the length */
	spack('F',n,len,filestr);	/* send an 'F' packet */

	switch(rpack(&len,&num,recpkt))
	{							/* What was the reply? */
		case 'N':				/* NAK */
			if (n != num--)
				return(state);	/* If NAK for next pack its like ACK */

		case 'Y':				/* ACK */
		{
			if (n != num)		/* If wrong ACK, fail */
				return(state);
			numtry = 0;			/* reset try counter */

			n = (n+1)%64;		/* and bump packet count */
			size = bufill(packet);	/* get first packet of data from file */
			return('D');		/* switch state to D */
		}

		case FALSE:				/* receive failure, fail */
			return(state);

		default:				/* Just abort */
			return('A');
	}
}


/*
 *	s d a t a
 */

sdata()
{
	int num, len;

	if (numtry++ > MAXTRY)		/* If too many tries, abort */
		return('A');

	spack('D',n,size,packet);	/* send a 'D' packet */

	switch(rpack(&len,&num,recpkt))
	{							/* What was the reply */
		case 'N':				/* NAK */
			if (n != num--)
				return(state);	/* If NAK for next pack its like ACK */

		case 'Y':				/* ACK */
		{
			if (n != num)		/* If wrong ACK, fail */
				return(state);
			numtry = 0;			/* reset try counter */
			n = (n+1)%64;		/* and bump packet count */

			if ((size = bufill(packet)) == EOF) /* get the data from file */
				return('Z');	/* if EOF set state to it */

			return('D');		/* switch state to 'D' */
		}

		case FALSE:				/* receive failure, fail */
			return(state);

		default:				/* just abort */
			return('A');
	}
}


/*
 *	s e o f
 */

seof()
{
	int num, len;

	if (numtry++ > MAXTRY)		/* If too many tries, abort */
		return('A');

	spack('Z',n,0,packet);		/* Send a 'Z' packet */

	switch(rpack(&len,&num,recpkt))
	{							/* What was the reply? */
		case 'N':				/* NAK */
			if (n != num--)
				return(state);	/* If NAK for next pack, its like ACK */

		case 'Y':				/* ACK */
		{
			if (n != num)		/* if wrong ACK, fail */
				return(state);
			numtry = 0;			/* reset try counter */
			n = (n+1)%64;		/* and bump packet count */

			close(fd);
			if (gnxtfl() == EOF)	/* No more files go to break */
				return('B');
			fd = open(filestr,0);	/* open the next file */

			return('F');		/* switch state to F */
		}

		case FALSE:				/* Receive failure, fail */
			return(state);

		default:				/* just abort */
			return('A');
	}
}


/*
 *	s b r e a k
 */

sbreak()
{
	int num, len;

	if (numtry++ > MAXTRY)			/* If too many tries abort */
		return('A');

	spack('B',n,0,packet);			/* Send a B packet */

	switch (rpack(&len,&num,recpkt))
	{								/* What was the reply? */
		case 'N':					/* NAK */
			if (n != num--)
				return(state);	/* If NAK for next pack its like ACK */

		case 'Y':				/* ACK */
		{
			if (n != num)		/* If wrong ACK, fail */
				return(state);
			numtry = 0;			/* reset try counter */
			n = (n+1)%64;		/* and bump packet count */
			return('C');		/* switch state to C */
		}

		case FALSE:				/* receive failure, fail */
			return(state);

		default:				/* just abort */
			return ('A');
	}
}
