/* FNS_C - QL-Kermit protocol functions Based on ckcfns.c, (C) Columbia University */ /* Include files */ #include "ram1_ker_h" /* Kermit definitions */ /* External variables */ extern int slen; /* Maximum send packet size */ extern int rlen; /* Maximum receive packet size */ extern int tslen; /* Send packet size in use */ extern int stmo; /* Timeout remote is to use */ extern int rtmo; /* Timeout we will use */ extern int n; /* Packet number */ extern int ttyfd; /* FD of TTY for I/O, 0 if remote */ extern int ttychid; /* Channel ID for ttyfd */ extern int tvalue; /* Current timeout value */ extern int debug; /* Level of debugging output */ extern int parity; /* Current parity setting */ extern int npad; /* Amount of padding remote needs */ extern int tnpad; /* Padding count in use */ extern int xfertyp; /* File transfer mode */ extern long filein; /* File bytes received */ extern long fileout; /* File bytes sent */ extern long totin; /* Total bytes received */ extern long totout; /* Total bytes sent */ extern bool timer; /* Timer enabled */ extern bool cxseen; /* File interruption flag */ extern bool czseen; /* Group interruption flag */ extern bool toscr; /* Screen data flag */ extern bool ebqflg; /* 8-bit quoting being done */ extern char ssop; /* SOP remote needs */ extern char rsop; /* SOP I need */ extern char seol; /* EOL for sending packets */ extern char reol; /* EOL for receiving packets */ extern char tseol; /* Sending EOL in use */ extern char quote; /* Sending control quote */ extern char pebq; /* 8-bit quote prefix */ extern char tquote; /* Receiving control quote */ extern char ebq; /* 8-bit quote in use */ extern unsigned char padch; /* Pad character remote needs */ extern unsigned char tpadc; /* Pad character in use */ extern char *ttyname; /* Name of TTY for transfer */ extern int fp; /* Local file for data transfer */ extern int _oserr; /* QDOS error code */ extern int oserr; /* Copy of above */ extern bool warn8; /* Lost 8th bit warning given */ extern int state; /* Current switcher state */ /* External functions */ extern bool chkquote(); /* Check for valid quote character */ extern bool tfput(); /* Put a byte to transfer file */ extern int tfget(); /* Get a byte from transfer file */ /* Local variables */ static int length; /* Length of last packet read */ /* TINIT - Initialise transaction */ tinit() { tseol = seol; /* Initialise sending EOL, */ tslen = slen; /* packet length */ tvalue = 50*rtmo; /* and timeout */ czseen = FALSE; /* Clear interrupt flags */ cxseen = FALSE; tnpad = npad; /* Initialise padding */ tpadc = padch; tquote = quote; /* and quote characters */ ebq = 0; ebqflg = FALSE; /* Reset 8-bit quote flag */ totin = totout = 0; /* Clear character counts */ } /* SPACK - Send a packet */ spack(type,num,len,data) char type; int num,len; char *data; { int i; /* Character loop counter */ char chksum; /* Checksum */ char buffer[110]; /* Packet buffer */ char *bufp; /* Buffer pointer */ if (debfull) /* Display outgoing packet? */ { if (data!=NULL) data[len] = '\0'; /* Null-terminate data for printing */ printf("spack: type=%c, num=%d, len=%d\n",type,num,len); if (data!=NULL) printf(" data=\"%s\"\n",data); } bufp = buffer; /* Set up buffer pointer */ *bufp++ = ssop; /* Packet marker (SOH) */ chksum = *bufp++ = tochar(len+3); /* Character count */ *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 = tseol; /* Add packet line terminator */ write(ttyfd,buffer,bufp-buffer+1); /* and send the packet */ for (i = 0; i>6)+ccsum)&077; /* compute final checksum */ if (ccsum!=rcsum) /* Checksum correct? */ { if (debon) printf("Received bad checksum\n"); return(BAD); } return((int) type); /* All OK, return packet type */ } /* BUFILL - Get a bufferful of data from the file that's being sent and encode it for transmission. */ int bufill(buff) char buff[]; { int i; /* Loop index */ char t; /* Character read from file */ int tt; /* For testing EOF */ int a7,b8; /* Split-up versions of above */ i = 0; /* Set up data buffer pointer */ while ((tt = tfget())!=EOF) /* Get the next character */ { fileout++; /* Count it */ t = (char) tt; a7 = t&0177; /* Get lower 7 bits */ b8 = t&0200; /* and 8th bit */ if (a7!=t && !warn8 && !ebqflg && parity!=PYNONE) { /* Check for data loss */ printf("Warning: 8th bits lost\n"); warn8 = TRUE; } if (ebqflg && b8!=0) /* EBQ required? */ { buff[i++] = ebq; /* Yes, put out prefix */ t = a7; /* and work on 7-bit character */ } if (a7=tslen-9) return(i); /* Conservative length check */ } if (i==0) return(EOF); /* Here only on EOF */ return(i); /* Handle partial buffer */ } /* BUFEMP - Put data from an incoming packet into a file */ bool bufemp(buff,len) char buff[]; int len; { int i; /* Counter */ char t; /* Character holder */ int a,a7,b8; /* Component parts of above */ char fbuf[MAXPACK]; /* File data buffer */ int fbufp = 0; /* Index into above */ for (i=0; i=0100 && a7<=0137) || a7=='?') a = ctl(a); /* Uncontrollify */ } t = (char) a | b8; /* Add in 8th bit */ if (toscr && t!=CR) putch(t); /* Screen output */ else if (!(t==CR && xfertyp==FTASC)) /* File output */ fbuf[fbufp++] = t; filein++; /* Count the character */ } if (!toscr) /* File output */ { if (write(fp,fbuf,fbufp)!=fbufp) /* Write to file */ { oserr = _oserr; /* Save error code */ return(FALSE); } } else if (n==1) putch('\n'); /* Set screen for DO results */ return(TRUE); } /* SPAR - Fill the data array with my Send-Init parameters */ int spar(data) char data[]; { data[0] = tochar(rlen); /* Biggest packet I can receive */ data[1] = tochar(stmo); /* When I want to be timed out */ data[2] = tochar(0); /* How much padding I need */ data[3] = ctl('\0'); /* Padding character I need */ data[4] = tochar(reol); /* End-Of-Line character I need */ data[5] = quote; /* Quote character I send */ if (parity!=PYNONE || ebqflg) /* 8-bit quoting required? */ { data[6] = pebq; /* Ask for what we have SET */ if (chkquote(ebq) || ebq=='Y') ebqflg = TRUE; /* If valid reply, set flag */ } else data[6] = 'Y'; /* Not required, just say we're willing */ data[7] = '1'; /* Checksum type 1 */ data[8] = ' '; /* No repeat count capability */ return(9); /* Return the length */ } /* RPAR - Get and analyse the remote's Send-Init parameters */ #define IFP if (length-->0) /* If field is present */ rpar(data) char data[]; { IFP tslen = min(unchar(data[0]),tslen); /* Maximum send packet size */ IFP tvalue = max(50*unchar(data[1]),tvalue); /* When I should time out */ IFP tnpad = max(unchar(data[2]),tnpad); /* Padding required */ IFP tpadc = ctl(data[3]); /* Padding character */ IFP tseol = unchar(data[4]); /* EOL character I must send */ IFP tquote = data[5]; /* Incoming data quote character */ IFP { ebq = data[6]; /* EBQ remote will use */ if (chkquote(ebq)) ebqflg = TRUE; /* If acceptable, we will too */ else if ((parity!=PYNONE || ebqflg) && ebq=='Y') { /* We need it, remote says OK */ ebqflg = TRUE; ebq = pebq; /* Use what we have SET */ } else if (ebq=='N') { ebqflg = FALSE; /* We need it, remote can't do */ } else ebqflg = FALSE; /* Some other reply */ } else ebqflg = FALSE; /* No reply */ if (tseol==0) tseol = '\r'; /* Check and set defaults */ if (tquote==0) tquote = quote; if (tslen<10) tslen = 10; if (debon) { printf("rpar: timeout=%d, length=%d, EOL=%d\n",tvalue/50,tslen,tseol); printf(" npad=%d, padchar=0%o, quote=%c\n",tnpad,tpadc,tquote); printf(" 8-bit quoting %s",(ebqflg ? "yes" : "no")); if (ebqflg) printf(", with %c",ebq); printf("\n"); } } /* ACK - Send an acknowledgement with no data */ ack() { spack('Y',n,0,0); } /* ACK1 - Send an acknowledgement with 1 character of data */ ack1(s) char *s; { spack('Y',n,1,s); } /* ACKN - Acknowledge a specific packet number */ ackn(num) int num; { spack('Y',num,0,0); } /* NAK - Send a negative acknowledegement */ nak() { spack('N',n,0,0); }