/* @(#)receive.c 1.1 1/26/85 */ /* * receive - routines for receiving data * * r e c s w */ #include "kermit.h" #include "errors.h" static char rinit (); static char rfile (); static char rdata (); VOID Receive () { DBUG_ENTER ("receive"); DBUG_2 ("rec", "begin receive attempt"); if (recsw () == FALSE) { (VOID) printf ("Receive failed.\n"); } else { (VOID) printf ("OK\n"); } DBUG_VOID_RETURN; } recsw () { DBUG_ENTER ("recsw"); DBUG_2 ("init", "initializing receive variables"); state = 'R'; /* receive is the start state */ n = 0; /* initialize message number */ numtry = 0; /* say no tries yet */ while (TRUE) { /* do this as long as necessary */ DBUG_3 ("states", "state %c found", state); switch (state) { case 'D': state = rdata (); break; /* data receive state */ case 'F': state = rfile (); break; /* fil receive state */ case 'R': state = rinit (); break; /* send initiate state */ case 'C': DBUG_RETURN (TRUE); /* complte state */ case 'A': DBUG_RETURN (FALSE); /* unknown state, abort */ } } } /* * r i n i t */ static char rinit () { auto int len; auto int num; register char newstate; DBUG_ENTER ("rinit"); if (numtry++ > MAXTRY) { newstate = 'A'; } else { DBUG_2 ("state", "begin receive init"); switch (rpack (&len, &num, packet)) { case 'S': /* send-init */ DBUG_2 ("init", "got S packet"); rpar (packet); /* get the init data */ spar (packet); /* fill up packet with init info */ spack ('Y', n, 6, packet); /* ACK with my parameters */ oldtry = numtry; numtry = 0; /* and start a new counter */ n = (n + 1) % 64; /* bump packet number */ newstate = 'F'; break; case FALSE: DBUG_2 ("init", "no S packet"); newstate = state; break; default: newstate = 'A'; break; } } DBUG_3 ("states", "new state %c", newstate); DBUG_RETURN (newstate); } /* * r f i l e */ static char rfile () { auto int num; auto int len; char *bp; register char newstate; DBUG_ENTER ("rfile"); if (numtry++ > MAXTRY) { DBUG_3 ("tries", "%d tries", numtry - 1); newstate = 'A'; } else { switch (rpack (&len, &num, packet)) { case 'S': DBUG_2 ("S", "got S packet"); if (oldtry++ > MAXTRY) { newstate = 'A'; } else if (num == n - 1) { spar (packet); spack ('Y', num, 6, packet); numtry = 0; newstate = state; } else { newstate = 'A'; } break; case 'Z': /* end-of-file */ if (oldtry++ > MAXTRY) { newstate = 'A'; } else if (num == n - 1) { /* acknowledge good packet */ spack ('Y', num, 0, packet); numtry = 0; newstate = state; } else { newstate = 'A'; } break; case 'F': /* file-header */ if (num != n) { newstate = 'A'; break; } DBUG_3 ("pack", "converting %s", packet); if (mflg) { for (bp = &packet[0]; *bp != NULL; bp++) { *bp = tolower(*bp); } } DBUG_3 ("files", "open file %s", packet); if (!getfil (packet)) { Error (RCVFILE, packet); newstate = 'A'; } else { if (host) { (VOID) printf ("Receiving %s\n", packet); } spack ('Y', n, 0, packet); /* acknowledge */ oldtry = numtry; numtry = 0; n = (n + 1) % 64; newstate = 'D'; } break; case 'B': if (num != n) { newstate = 'A'; } else { spack ('Y', n, 0, packet); newstate = 'C'; } break; case FALSE: newstate = state; break; default: newstate = 'A'; break; } } DBUG_3 ("states", "new state %c", newstate); DBUG_RETURN (newstate); } /* * r d a t a */ static char rdata () { auto int num; auto int len; register char newstate; DBUG_ENTER ("rdata"); DBUG_2 ("rcv", "receive data"); if (numtry++ > MAXTRY) { newstate = 'A'; } else { switch (rpack (&len, &num, packet)) { /* get packet */ case 'D': /* data */ DBUG_2 ("rcv", "got D packet"); DBUG_3 ("rcv", "length %d", len); if (num != n) { /* right packet? */ if (oldtry++ > MAXTRY) { newstate = 'A'; } else if (num == n - 1) { spar (packet); spack ('Y', num, 6, packet); numtry = 0; newstate = state; } else { newstate = 'A'; } } else { bufemp (packet, fd, len); spack ('Y', n, 0, packet); oldtry = numtry; numtry = 0; n = (n + 1) % 64; newstate = 'D'; } break; case 'F': /* file-send */ DBUG_2 ("rcv", "got F packet"); if (oldtry++ > MAXTRY) { newstate = 'A'; } else if (num == n - 1) { /* ack good packet */ spack ('Y', num, 0, packet); numtry = 0; newstate = state; } else { newstate = 'A'; } break; case 'Z': /* end-of-file */ DBUG_2 ("rcv", "got Z packet"); if (num != n) { newstate = 'A'; } else { spack ('Y', n, 0, packet); /* say OK */ (VOID) close (fd); /* close up file */ n = (n + 1) % 64; newstate = 'F'; } break; case FALSE: newstate = state; break; default: newstate = 'A'; break; } } DBUG_3 ("states", "new state %c", newstate); DBUG_RETURN (newstate); }