
#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);  /* NAK for next pack = 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);  /* NAK for next packet = 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);  /* NAK for next pack = 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);  /* NAK for next packet=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);  /* NAK for next pack = 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');
        }
}
