/* kerrec.c kermit protocol file receive support. */ #include #include #include "ed.h" #include "kermit.h" extern char getfiln[NFILEN]; /* * r e c s w * * This is the state table switcher for receiving files. */ recsw() { state = 'R'; /* Receive-Init is the start state */ n = np = 0; /* Initialize message number */ numtry = 0; /* Say no tries yet */ while(TRUE) { switch(state) /* Do until done */ { case 'R': state = rinit(); mlwrite("[Awaiting remote init]"); break; /* Receive-Init */ case 'F': state = rfile(); break; /* Receive-File */ case 'D': state = rdata(); break; /* Receive-Data */ case 'C': return(TRUE); /* Complete state */ case 'A': return(FALSE); /* "Abort" state */ } } } /* * astget.c server function GET * implemented by B. Nebel */ getsw() { int result; flushinput(); spack('R',0,strlen(getfiln),getfiln); result = recsw(); return (result); } /* * r i n i t * * Receive Initialization */ char rinit() { int len, num; /* Packet length, number */ if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */ switch(rpack(&len,&num,packet)) /* Get a packet */ { case 'S': /* Send-Init */ rpar(packet,len); /* Get the other side's init data */ len = spar(packet); /* Fill up packet with my init info */ spack('Y',n,len,packet); /* ACK with my parameters */ oldtry = numtry; /* Save old try count */ numtry = 0; /* Start a new counter */ n = (n+1)%64; /* Bump packet number, mod 64 */ return('F'); /* Enter File-Receive state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: /* Didn't get packet */ spack('N',n,0,NULLPTR); /* Return a NAK */ return(state); /* Keep trying */ default: return('A'); /* Some other packet type, "abort" */ } } /* * r f i l e * * Receive File Header */ char rfile() { int num, len; /* Packet number, length */ if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */ switch(rpack(&len,&num,packet)) /* Get a packet */ { case 'S': /* Send-Init, maybe our ACK lost */ /* If too many tries "abort" */ if (oldtry++ > MAXTRY) return('A'); if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again with */ len = spar(packet); /* our Send-Init parameters */ spack('Y',num,len,packet); numtry = 0; /* Reset try counter */ return(state); /* Stay in this state */ } else return('A'); /* Not previous packet, "abort" */ case 'Z': /* End-Of-File */ if (oldtry++ > MAXTRY) return('A'); if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again. */ spack('Y',num,0,NULLPTR); numtry = 0; return(state); /* Stay in this state */ } else return('A'); /* Not previous packet, "abort" */ case 'F': /* File Header (just what we want) */ /* The packet number must be right */ if (num != n) return('A'); mlwrite("[Receiving %s as %s]",packet,curbp->b_bname); spack('Y',n,0,NULLPTR); /* Acknowledge the file header */ oldtry = numtry; /* Reset try counters */ numtry = 0; n = (n+1)%64; /* Bump packet number, mod 64 */ return('D'); /* Switch to Data state */ case 'B': /* Break transmission (EOT) */ if (num != n) return ('A'); /* Need right packet number here */ spack('Y',n,0,NULLPTR); /* Say OK */ return('C'); /* Go to complete state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: /* Didn't get packet */ spack('N',n,0,NULLPTR); /* Return a NAK */ return(state); /* Keep trying */ default: return ('A'); /* Some other packet, "abort" */ } } /* * r d a t a * * Receive Data */ char rdata() { int num, len; /* Packet number, length */ if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */ switch(rpack(&len,&num,packet)) /* Get packet */ { case 'D': /* Got Data packet */ if (num != n) /* Right packet? */ { /* No */ if (oldtry++ > MAXTRY) return('A'); /* If too many tries, abort */ if (num == ((n==0) ? 63:n-1)) { /* Else check previous packet again? */ spack('Y',num,0,NULLPTR); /* Yes, re-ACK it */ numtry = 0; /* Reset try counter */ return(state); /* Don't write out data! */ } else return('A'); /* sorry, wrong number */ } /* Got data with right packet number */ bufemp(packet,len); /* Write the data to the file */ spack('Y',n,0,NULLPTR); /* Acknowledge the packet */ oldtry = numtry; /* Reset the try counters */ numtry = 0; /* ... */ mlwrite("[Receiving packet: %d]", ++np); n = (n+1)%64; /* Bump packet number, mod 64 */ return('D'); /* Remain in data state */ case 'F': /* Got a File Header */ if (oldtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */ if (num == ((n==0) ? 63:n-1)) /* Else check packet number */ { /* It was the previous one */ spack('Y',num,0,NULLPTR); /* ACK it again */ numtry = 0; /* Reset try counter */ return(state); /* Stay in Data state */ } else return('A'); /* Not previous packet, "abort" */ case 'Z': /* End-Of-File */ /* Must have right packet number */ if (num != n) return('A'); spack('Y',n,0,NULLPTR); /* OK, ACK it. */ n = (n+1)%64; /* Bump packet number */ return('F'); /* Go back to Receive File state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: /* Didn't get packet */ spack('N',n,0,NULLPTR); /* Return a NAK */ return(state); /* Keep trying */ default: return('A'); /* Some other packet, "abort" */ } } /* * r p a c k * * Read a Packet */ char rpack(len,num,data) int *len, *num; /* Packet length, number */ char *data; /* Packet data */ { register int i, done; /* Data character number, loop exit */ register char t, /* Current input character */ cchksum, /* Our (computed) checksum */ rchksum, /* Checksum received from other host */ type; /* Packet type */ do { if (Bconstat(2)) if (ttgetc() == 0x07) /* ^G abort */ { mlwrite("User ABORT"); (*term.t_beep)(); return('A'); } if (!Cauxis()) continue; else t = (char)readaux()& 0x7f; }while (t != SOH); /* Wait for packet header */ done = FALSE; /* Got SOH, init loop */ while (!done) /* Loop to get a packet */ { if (Bconstat(2)) if (ttgetc() == 0x07) /* ^G abort */ { mlwrite("User ABORT"); (*term.t_beep)(); return('A'); } t = (char)readaux(); /* Get character */ if (t == SOH) continue; /* Resynchronize if SOH */ cchksum = t; /* Start the checksum */ *len = unchar(t)-3; /* Character count */ t = (char)readaux(); /* Get character */ if (t == SOH) continue; /* Resynchronize if SOH */ cchksum += t; /* Update checksum */ *num = unchar(t); /* Packet number */ t = (char)readaux(); /* Get character */ if (t == SOH) continue; /* Resynchronize if SOH */ cchksum += t; /* Update checksum */ type = t; /* Packet type */ for (i=0; i<*len; i++) /* The data itself, if any */ { /* Loop for character count */ if (Bconstat(2)) if (ttgetc() == 0x07) /* ^G abort */ { mlwrite("User ABORT"); (*term.t_beep)(); return('A'); } t = (char)readaux(); /* Get character */ if (t == SOH) continue; /* Resynch if SOH */ cchksum += t; /* Update checksum */ data[i] = t; /* Put it in the data buffer */ } data[*len] = 0; /* Mark the end of the data */ t = (char)readaux(); /* Get last character (checksum) */ rchksum = unchar(t); /* Convert to numeric */ t = (char)readaux(); /* get EOL character and toss it */ if (t == SOH) continue; /* Resynchronize if SOH */ done = TRUE; /* Got checksum, done */ } /* Fold in bits 7,8 to compute */ cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */ if (cchksum != rchksum) return((char)FALSE); return(type); /* All OK, return packet type */ } /* r p a r * * Get the other host's send-init parameters * */ void rpar(data,len) char data[]; int len; { spsiz = DEFMAXL; /* default packet size */ timint = DEFTIME; pad = DEFPAD; padchar = DEFPADC; eol = DEFEOL; quotech = DEFQUOTE; qbin = DEFQBIN; switch (len){ default: case 10: /* attributes */ case 9: /* repeat count */ case 8: /* Check type */ case 7: /* 8 bit quoting */ qbin = data[6]; if (((qbin >='!') && (qbin <= '>')) || ((qbin >= '`')&&(qbin <= '~'))) /* qflag = TRUE; */ en8quote(TRUE); /* jgc dec 25th. 1985 */ case 6: /* Incoming data quote character */ quotech = data[5]; case 5: /* EOL character I must send */ eol = unchar(data[4]); case 4: /* Padding character I must send */ padchar = ctl(data[3]); case 3: /* Number of pads to send */ pad = unchar(data[2]); case 2: /* When I should time out */ timint = unchar(data[1]); if ((timint > MAXTIM) || (timint < MINTIM)) timint = MYTIME; case 1: /* Maximum send packet size */ spsiz = unchar(data[0]); case 0: break; } if (qflag) { if (qbin == 'N') mlwrite("Can't do 8 bit quoting"); else if (qbin == 'Y') qbin = QBIN; } } /* * s p a r * * Fill the data array with my send-init parameters * */ int spar(data) char data[]; { data[0] = tochar(MYPACKSIZ); /* Biggest packet I can receive */ data[1] = tochar(MYTIME); /* When I want to be timed out */ data[2] = tochar(MYPAD); /* How much padding I need */ data[3] = ctl(MYPCHAR); /* Padding character I want */ data[4] = tochar(MYEOL); /* End-Of-Line character I want */ data[5] = MYQUOTE; /* Control-Quote character I send */ data[6] = qflag?QBIN:'Y'; /* Request 8 bit quoting */ return (7); /* return number of parameters */ } /* * s p a c k * * Send a Packet */ void spack(type,num,len,data) char type, *data; int num, len; { register int i; /* Character loop counter */ char chksum, buffer[100]; /* Checksum, packet buffer */ register char *bufp; /* Buffer pointer */ bufp = buffer; /* Set up buffer pointer */ for (i=1; i<=pad; i++) sendaux(padchar); /* Issue any padding */ *bufp++ = SOH; /* Packet marker, ASCII 1 (SOH) */ *bufp++ = tochar(len+3); /* Send the character count */ chksum = tochar(len+3); /* Initialize the checksum */ *bufp++ = tochar(num); /* Packet number */ chksum += tochar(num); /* Update checksum */ *bufp++ = type; /* Packet type */ chksum += type; /* Update checksum */ for (i=0; i> 6)+chksum)&077; /* Compute final checksum */ *bufp++ = tochar(chksum); /* Put it in the packet */ *bufp = eol; /* Extra-packet line terminator */ sauxstr( buffer,((int)bufp-(int)buffer+1)); /* Send the packet */ }