/* @(#)send.c 1.1 1/26/85 */ #include "kermit.h" static char sinit (); static char sfile (); VOID Send (argv) char *argv[]; { extern int optind; DBUG_ENTER ("send"); DBUG_2 ("send", "begin send attempt"); filnam = argv[optind]; if (filnam == NULL) { Usage (); } filelist = &argv[optind+1]; if (sendsw () == FALSE) { (VOID) printf ("Send failed.\n"); } else { (VOID) printf ("OK\n"); } DBUG_VOID_RETURN; } /* * 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 () { DBUG_ENTER ("sendsw"); state = 'S'; numtry = 0; DBUG_2 ("states", "state S set"); while (TRUE) { DBUG_3 ("states", "state %c found", state); switch (state) { case 'D': /* Data-Send state */ state = sdata (); break; case 'F': /* File-Send */ state = sfile (); break; case 'Z': /* End-of-File */ state = seof (); break; case 'S': /* Send-Init */ state = sinit (); break; case 'B': /* Break-Send */ state = sbreak (); break; case 'C': /* Complete */ DBUG_RETURN (TRUE); case 'A': /* Abort */ DBUG_RETURN (FALSE); default: /* Unknown, abort */ DBUG_RETURN (FALSE); } } } /* * s i n i t */ static char sinit () { int num; int len; register char newstate; DBUG_ENTER ("sinit"); DBUG_2 ("sinit", "begin init attempt"); if (numtry++ > MAXTRY) { DBUG_3 ("tries", "%d tries", numtry - 1); newstate = 'A'; } else { spar (packet); DBUG_3 ("n", "packet number %d", n); spack ('S', n, 6, packet); switch (rpack (&len, &num, recpkt)) { case 'N': DBUG_2 ("nak", "got N packet"); if (n != num--) { newstate = state; break; } case 'Y': DBUG_2 ("ack", "got Y packet"); if (n != num) { newstate = state; break; } 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; DBUG_3 ("files", "open file %s", filnam); fd = open (filnam, 0, 0777); if (fd < 0) { newstate = 'A'; } else { if (host) { (VOID) printf ("Sending %s\n", filnam); } newstate = 'F'; } break; case FALSE: newstate = state; break; default: newstate = 'A'; break; } } DBUG_3 ("states", "new state %c", newstate); DBUG_RETURN (newstate); } /* * s f i l e */ static char sfile () { int num; int len; register char newstate; DBUG_ENTER ("sfile"); DBUG_2 ("sfile", "begin send file attempt"); if (numtry++ > MAXTRY) { DBUG_3 ("tries", "%d tries", numtry - 1); newstate = 'A'; } else { for (len = 0; filnam[len] != '\0'; len++); /* count the length */ len++; spack ('F', n, len, filnam); /* send an 'F' pkt */ switch (rpack (&len, &num, recpkt)) { case 'N': /* NAK */ DBUG_2 ("nak", "got N packet"); if (n != num--) { newstate = state; break; } case 'Y': /* ACK */ DBUG_2 ("ack", "got Y packet"); if (n != num) { /* Wrong ACK, fail */ newstate = state; } else { numtry = 0; n = (n + 1) % 64; size = bufill (packet); newstate = 'D'; } break; case FALSE: newstate = state; break; default: newstate = 'A'; break; } } DBUG_3 ("states", "new state %c", newstate); DBUG_RETURN (newstate); } /* * s d a t a */ sdata () { int num; int len; register int newstate; DBUG_ENTER ("sdata"); if (numtry++ > MAXTRY) { /* If too many tries, abort */ newstate = 'A'; } else { spack ('D', n, size, packet); /* send a 'D' packet */ switch (rpack (&len, &num, recpkt)) { /* What was the reply */ case 'N': /* NAK */ DBUG_2 ("nak", "got N packet"); if (n != num--) { newstate = state; break; } case 'Y': /* ACK */ DBUG_2 ("ack", "got Y packet"); if (n != num) { /* Wrong ACK, fail */ newstate = state; break; } numtry = 0; /* rest try counter */ n = (n + 1) % 64; if ((size = bufill (packet)) == EOF) { newstate = 'Z'; } else { newstate = 'D'; } break; case FALSE: newstate = state; break; default: newstate = 'A'; break; } } DBUG_3 ("states", "new state %c", newstate); DBUG_RETURN (newstate); } /* * s e o f */ seof () { int num; int len; register int newstate; DBUG_ENTER ("seof"); DBUG_2 ("eof", "begin seof"); if (numtry++ > MAXTRY) { DBUG_3 ("tries", "%d tries", numtry - 1); newstate = 'A'; } else { spack ('Z', n, 0, packet); /* Send a 'Z' packet */ DBUG_2 ("packets", "Z packet sent"); switch (rpack (&len, &num, recpkt)) { /* What was the reply? */ case 'N': /* NAK */ DBUG_2 ("nak", "got N packet"); if (n != num--) { newstate = state; break; } case 'Y': /* ACK */ DBUG_2 ("ack", "got Y packet"); if (n != num) { /* if wrong ACK, fail */ newstate = state; break; } numtry = 0; /* reset try counter */ /* n = (n+1)%64; */ DBUG_3 ("files", "closing file %s", filnam); (VOID) close (fd); /* close the input file */ DBUG_2 ("files", "getting next file"); if (gnxtfl () == FALSE) { /* No more files go? */ n = (n + 1) % 64; newstate = 'B'; } else { DBUG_3 ("files", "new file is %s", filnam); newstate = 'S'; } break; case FALSE: newstate = state; break; default: newstate = 'A'; break; } } DBUG_3 ("states", "new state %c", newstate); DBUG_RETURN (newstate); } /* * s b r e a k */ sbreak () { int num; int len; register int newstate; DBUG_ENTER ("sbreak"); DBUG_2 ("break", "begin break transmission"); if (numtry++ > MAXTRY) { /* If too many tries abort */ DBUG_3 ("tries", "%d tries", numtry - 1); newstate = 'A'; } else { spack ('B', n, 0, packet); /* Send a B packet */ switch (rpack (&len, &num, recpkt)) { /* What was the reply? */ case 'N': /* NAK */ DBUG_2 ("nak", "got N packet"); if (n != num--) { newstate = state; break; } case 'Y': /* ACK */ DBUG_2 ("ack", "got Y packet"); if (n != num) { newstate = state; } else { numtry = 0; /* reset try counter */ n = (n + 1) % 64; /* and bump packet count */ newstate = 'C'; } break; case FALSE: newstate = state; break; default: newstate = 'A'; break; } } DBUG_3 ("states", "new state %c", newstate); DBUG_RETURN (newstate); }