/* kertrans.c transfer and send functions to support file sends through * ueMail. All functions available only through kermit(). */ #include #include #include "ed.h" #include "kermit.h" /* ASCII transmit. Some delay ability. Use for short files only or over * a direct link. */ extern int emacsfile; extern char getfiln[NFILEN]; int trans() { register int c; register int ln = 0; while (curwp->w_dotp != curbp->b_linep) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (curwp->w_doto == llength(curwp->w_dotp)) { mlwrite("[Transmitting line: %d]",++ln); if (!emacsfile) c = '\r'; else c = '\n'; } while (!(int)Bcostat(1)) /* check for line ready */ { if (Bconstat(2)) if (ttgetc()==0x07) return(FALSE); } sendaux(c); if (!forwchar(FALSE, 1)) return(FALSE); } if(!emacsfile) { while (!(int)Bcostat(1)) { if (Bconstat(2)) if (ttgetc()==0x07) return(FALSE); } sendaux(CLEAR); } return(ln); } /* * 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. * */ int sendsw() { state = 'S'; /* Send initiate is the start state */ n = np = 0; /* Initialize message number */ numtry = 0; /* Say no tries yet */ while(TRUE) /* Do this as long as necessary */ { switch(state) { case 'S': mlwrite("[Sending init packet]"); 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': return (FALSE); /* "Abort" */ default: 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 */ /* If too many tries, give up */ if (numtry++ > MAXTRY) return('A'); len = spar(packet); /* Fill up init info packet */ spack('S',n,len,packet); /* Send an S packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': return(state); /* NAK, try it again */ case 'Y': /* ACK */ if (n != num) /* If wrong ACK, stay in S state */ return(state); /* and try again */ rpar(recpkt,len); /* 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('A'); /* abort */ case FALSE: return(state); /* Receive failure, try again */ default: return('A'); /* Anything else, just "abort" */ } } /* * s f i l e * * Send File Header. */ char sfile() { int num, len; /* Packet number, length */ /* If too many tries, give up */ if (numtry++ > MAXTRY) return('A'); len = strlen(getfiln); mlwrite("[Sending %s as %s]",curbp->b_bname,getfiln); spack('F',n,len,getfiln); /* Send an F packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ /* unless it's NAK for next packet */ num = (--num<0 ? 63:num); if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, stay in F state */ 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('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in F state */ default: 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) return('A'); /* If too many tries, give up */ spack('D',n,(int)size,packet); /* Send a D packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ /* unless it's NAK for next packet */ num = (--num<0 ? 63:num); if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, fail */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* Bump packet count */ mlwrite("[Sending packet: %d]",++np); if ((size=bufill(packet))==EOF) /* Get data from file */ return('Z'); /* If EOF set state to that */ return('D'); /* Got data, stay in state D */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in D */ default: return('A'); /* Anything else, "abort" */ } } /* * s e o f * * Send End-Of-File. */ char seof() { int num, len; /* Packet number, length */ if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */ 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, */ /* unless it's NAK for next packet, */ num = (--num<0 ? 63:num); if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, hold out */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* and bump packet count */ return('B'); /* if not, break, EOT, all done */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in Z */ default: 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) return('A'); /* If too many tries "abort" */ 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, */ /* unless NAK for previous packet, */ num = (--num<0 ? 63:num); if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, fail */ 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('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in B */ default: return ('A'); /* Other, "abort" */ } }