/* * astsen.c send file routines of ATARI ST kermit */ #include #include #include "astobj.h" #include "astinc.h" extern FILE *fopen(), *fopenb(); /* * s e n d s w * * Sendsw is the state table switcher for sending files. It loops until * either it finishes, or an error is encountered. The routines called * by sendsw are responsible for changing the state. * */ sendsw() { char sinit(), sfile(), sdata(), seof(), sbreak(); start_timer(&starttrans); state = 'S'; /* Send initiate is the start state */ n = 0; /* Initialize message number */ numtry = 0; /* Say no tries yet */ for (;;) { /* Do this as long as necessary */ msgdeb(MSGDSTAT,state,n); bps = ((timer(starttrans) != 0) ? (bytecnt/timer(starttrans)) : 0); dt_packets(TRUE); switch(state) { case 'S': state = sinit(); break; /* Send-Init */ case 'F': state = sfile(); break; /* Send-File */ case 'D': state = sdata(); break; /* Send-Data */ case 'Z': state = seof(); break; /* Send-End-of-File */ case 'B': state = sbreak(); break;/* Send-Break */ case 'C': return (TRUE); /* Complete */ case 'A': spack('E', n, 5, "Abort"); /* error packet */ return (FALSE); /* "Abort" */ case 'E': return(FALSE); /* "Error Abort" */ default: msgdeb(MSGSTATE); return (FALSE); /* Unknown, fail */ } } } /* * s i n i t * * Send Initiate: send this host's parameters and get other side's back. */ char sinit() { int num, len; /* Packet number, length */ int i; if (numtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER); return('A');}; ebq = TRUE; /* assume 7 bit transfer for init */ spar(packet); /* Fill up init info packet */ flushinput(); /* Flush pending input */ spack('S', n, 7, packet); /* Send an S packet */ for (i = 0; i <= 10; i++) recpkt[i] = 0; switch(rpack(&len, &num, recpkt)) { /* What was the reply? */ case 'N': nakcnt ++; return(state); /* NAK, try it again */ case 'Y': /* ACK */ if (n != num) /* If wrong ACK, stay in S state */ { nakcnt++; return(state); /* and try again */ }; n_total++; rpar(recpkt); /* Get other side's init info */ numtry = 0; /* Reset try counter */ n = (n + 1) % 64; /* Bump packet count */ return('F'); /* OK, switch state to F */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('E'); /* abort */ case FALSE: nakcnt++; return(state); /* Receive failure, try again */ case 'A': return('A'); /* user abort */ default: msgall(KRPROERR,MSGPROER); return('A'); /* Anything else, just "abort" */ } } /* * s f i l e * * Send File Header. */ char sfile() { int num, len; /* Packet number, length */ char *newfilnam, /* Pointer to file name to send */ *cp; /* char pointer */ if (numtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER);return('A');}; if (fp == NULL) { /* If not already open, */ filnam1[0] = '\0'; dt_files(TRUE); msgdeb(MSGFOPN,filnam); /* open the file to be sent */ if (image) fp = fopenb(filnam,"r"); else fp = fopen(filnam,"r"); if (fp == NULL) { /* bad file pointer, give up */ msgall(KERRFOPN,MSGERRFO); return('A'); }; }; strcpy(filnam1, filnam); /* Copy file name */ newfilnam = cp = filnam1; len = strlen(filnam1); /* Compute length of new filename */ spack('F', n, len, newfilnam); /* Send an F packet */ switch(rpack(&len, &num, recpkt)) { /* What was the reply? */ case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless it's NAK for next packet */ if (n != num) /* which is just like an ACK for */ {nakcnt++;return(state);}; case 'Y': /* ACK */ if (n != num) { nakcnt++; return(state); /* and try again */ }; msgall(-1,MSGSFASF,filnam, newfilnam); dt_files(TRUE); n_total++; numtry = 0; /* Reset try counter */ n = (n + 1) % 64; /* Bump packet count */ size = bufill(packet); /* Get first data from file */ return('D'); /* Switch state to D */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('E'); /* abort */ case FALSE: nakcnt++; return(state); /* Receive failure, stay in F state */ case 'A': return('A'); /* user abort */ default: msgall(KRPROERR,MSGPROER); return('A'); /* Something else, just "abort" */ } } /* * s d a t a * * Send File Data */ char sdata() { int num, len; /* Packet number, length */ if (numtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER);return('A');}; spack('D', n, size, packet); /* Send a D packet */ switch (rpack(&len, &num, recpkt)) { /* What was the reply? */ case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless it's next packet's NAK */ if (n != num) /* which is just like an ACK for */ { nakcnt++; return(state); /* and try again */ }; case 'Y': /* ACK */ if (n != num) { nakcnt++; return(state); /* and try again */ }; n_total++; numtry = 0; /* Reset try counter */ n = (n+1)%64; /* Bump packet count */ if ((size = bufill(packet)) == EOF) /* Get data from file */ return('Z'); /* If EOF set state to that */ if (ferror(fp)) {msgall(KRFATFER,MSGFATFE); return('A'); }; return('D'); /* Got data, stay in state D */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('E'); /* abort */ case FALSE: nakcnt++; return(state); /* Receive failure, stay in D */ case 'A': return('A'); /* user abort */ default: msgall(KRPROERR,MSGPROER); return('A'); /* Anything else, "abort" */ } } /* * s e o f * * Send End-Of-File. */ char seof() { int num, len; /* Packet number, length */ if (numtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER);return('A');}; spack('Z', n, 0, packet); /* Send a 'Z' packet */ switch(rpack(&len, &num, recpkt)) { /* What was the reply? */ case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless it's next packet's NAK, */ if (n != num) /* which is just like an ACK for */ { nakcnt++; return(state); /* and try again */ }; case 'Y': /* ACK */ if (n != num) { nakcnt++; return(state); /* and try again */ }; n_total++; filecnt++; numtry = 0; /* Reset try counter */ n = (n+1)%64; /* and bump packet count */ msgall(-1,MSGTREOF,filnam); fclose(fp); /* Close the input file */ fp = NULL; /* Set flag indicating no file open */ msgdeb(MSGFNEXT); if (fnxtfil() == FALSE) /* No more files go? */ return('B'); /* if not, break, EOT, all done */ msgdeb(MSGNEWFI,filnam); return('F'); /* More files, switch state to F */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('E'); /* abort */ case FALSE: nakcnt++; return(state); /* Receive failure, stay in Z */ case 'A': return('A'); /* user abort */ default: msgall(KRPROERR,MSGPROER); return('A'); /* Something else, "abort" */ } } /* * s b r e a k * * Send Break (EOT) */ char sbreak() { int num, len; /* Packet number, length */ if (numtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER);return('A');}; spack('B', n, 0, packet); /* Send a B packet */ switch (rpack(&len, &num, recpkt)) { /* What was the reply? */ case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless previous packet's NAK, */ if (n != num) /* which is just like an ACK for */ { nakcnt++; return(state); /* and try again */ }; case 'Y': /* ACK */ if (n != num) { nakcnt++; return(state); /* and try again */ }; n_total++; numtry = 0; /* Reset try counter */ n = (n+1)%64; /* and bump packet count */ return('C'); /* Switch state to Complete */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('E'); /* abort */ case FALSE: nakcnt++; return(state); /* Receive failure, stay in B */ case 'A': return('A'); /* user abort */ default: msgall(KRPROERR,MSGPROER); return ('A'); /* Other, "abort" */ } }