/***********************************************************************/ /* File KLINE.C - Comms-line handling procedures for RML Kermit; Chris Kennington RML. 9th July 1985. */ #define DEFS1 1 #define DEFS2 1 #include "stdio.h" #include "b:kext.h" /* local globals for nextin/nextout */ static int fuzzy = 20000; /* arbitry value */ static int ret; static char dummy, typout; static char comerr[] = "Comms err %x"; static char enter[] = " Enter %s for mainframe:\r> "; connect() /* keyboard/screen to comms line relay */ /* Reads keyboard and transmits to line; reads line and outputs to screen; checks comms line for error conditions. */ { char c, cn, conn; static char pager = 0, *data[5]; int in; printmsg("Connecting you to remote mainframe ... "); keyconn(); /* make arrows valid */ outc(NL); kmode = CONN; while (kmode == CONN) { /* until stopped */ if (keyget(&c) != 0) { if (echo != 0) outc(c); cn = 100; while (cn-- > 0) if (s4put(1,&c) > 0) break; if (cn == 0) bell(); } if ( (in = s4get7(1,&data)) == 1 ) { #ifndef MPUZ80 if (*data != LF) #endif outfc(*data); } else if (in != 0) { outc(NL); printmsg("Comms error code %x; ", in); while (s4test() == in) ; } } /* end switch */ /* broken out by changing kmode */ return; } /* End of connect() */ flushinput() /* Dump all pending input to clear stacked up NAK's. */ { char rubbish[11]; while (s4get(10,rubbish) > 0) ; } /* end of flushinput */ inctry() /* increment tries & pkt-# */ /* used by both recieve & send routines */ { oldtry = numtry; numtry = 0; n = (n+1)%64; return; } /* end of inctry() */ /* Line-I/O Routines for sending/receiving files */ static nextab() /* set abort-flag if CTLC */ { if (dummy == CTLC) { /* treat ctlc as abort */ printmsg("Abort transfer"); if (confirm() == TRUE) abtflag = 1; dummy = 0; } return; } /* end of nextab() */ nextin(ic) /* next char from line */ /* strips parity bit if !image; handles fuzzy timeout; returns 0, but 1 if either abtflag or nakflag has been set */ char *ic; { int r; abtflag = nakflag = 0; One: while ( (ret = (image) ? s4get(1,ic) : s4get7(1,ic)) == 0 ) { keyget(&dummy); nextab(); if ( (abtflag+nakflag) != 0 ) return(1); if (--fuzzy == 0) { /* timer expired */ nakflag = 1; ++timouts; if (list == 1) outc('T'); if (list > 2) txtout("\rDbg: Timeout."); return(1); } } while (ret < 0) { /* error */ printmsg(comerr,ret); while ( (r = (image) ? s4get(1,ic) : s4get7(1,ic)) == ret) { keyget(&dummy); if ( (abtflag+nakflag) != 0 ) return(1); } if (r == 0) goto One; ret = r; } if (list > 4) outc(*ic); if (*ic == SOH) fuzzy = fuzz[env]; /* fuzzy timer re-set on SOH only */ return(abtflag+nakflag); } /* end of nextin() */ nextout(c) /* next char to line */ /* returns 0, but 1 if either abtflag or nakflag has been set */ char c; { int r; abtflag = nakflag = 0; One: while ( (ret = s4put(1,&c)) == 0 ) { keyget(&dummy); nextab(); if ( (abtflag+nakflag) != 0 ) return(1); } while (ret < 0) { /* error */ printmsg(comerr,ret); while ( (r = s4put(1,&c)) == ret) { keyget(&dummy); if ( (abtflag+nakflag) != 0 ) return(1); } if (r == 0) goto One; ret = r; } if (list > 4) outc(c); keyget(&dummy); return(abtflag+nakflag); } /* end of nextout() */ char rpack(len,num,data) /* Read a Packet */ /* If !image, nextin() has stripped the parity bit. */ int *len, *num; /* Packet length, number */ char *data; /* Packet data */ { int i, done; /* Data character number, loop exit */ char t, /* Current input character */ cchksum, /* Our (computed) checksum */ rchksum; /* Checksum received from other host */ static int oldnum = 63; Top: fuzzy = fuzz[env]; /* set timer */ t = type = 0; /* could be garbage */ *len = 0; /* in case timeout */ while (t != SOH) if (nextin(&t) != 0) { type = 'T'; goto Flag; } done = FALSE; /* Got SOH, init loop */ while (!done) { /* Loop to get a packet */ if (nextin(&t) != 0) /* Get length character */ break; cchksum = t; /* Start the checksum */ if (t == SOH) continue; /* Resynchronize if SOH */ t &= 0x7f; /* 7-bit protocol char */ if ( (*len = unchar(t)-3) < 0 ) /* Character count */ return(FALSE); /* protect against bad length */ if (nextin(&t) != 0) /* Get packet-number character */ break; cchksum = cchksum + t; /* Update checksum */ t &= 0x7f; /* 7-bit protocol char */ if (t == SOH) continue; /* Resynchronize if SOH */ *num = unchar(t); /* Packet number */ if (*num == oldnum) ++dupes; /* its a duplicate */ else oldnum = *num; vtout(LOCSEQ,t|0x80); if (nextin(&t) != 0) /* Get packet-type character */ break; cchksum = cchksum + t; /* Update checksum */ t &= 0x7f; /* 7-bit protocol char */ if (t == SOH) continue; /* Resynchronize if SOH */ if ( (type = t) == 'N' ) { ++naxin; /* its a NAK */ if (list == 1) outc('N'); } if (type == typout) goto Top; /* its an echo */ vtout(LOCIN,type); for (i=0; i<*len; i++) { /* The data itself, if any */ if (nextin(&t) != 0) /* Get data character */ break; cchksum = cchksum + t; /* Update checksum */ data[i] = t; /* Put it in the data buffer */ t &= 0x7f; /* 7-bit char */ if (t == SOH) break; /* stop if SOH */ } if (t == SOH) continue; /* Resynchronize if SOH */ if ( (nakflag+abtflag) != 0 ) break; data[*len] = 0; /* Mark the end of the data */ if (nextin(&t) != 0) /* Get checksum character */ break; rchksum = unchar(t); /* Convert to numeric */ done = TRUE; /* Got checksum, done */ } flushinput(); /* discard anything stacked */ if ( (list > 3) && ( (nakflag+abtflag) == 0 ) ) { /* Display */ outc(CR); printf(" Packet in: type %c, num %d, len%d;",type,*num,*len); outc(CR); if (*len != 0) { data[*len] = 0; printf(" data: \"%s\";",data); outc(CR); } } Flag: /* check for user abort or nak */ vtout(LOCIN,type|0x80); /* inverse of type */ if (nakflag != 0) return(FALSE); /* cause NAK to be sent */ if (abtflag != 0) { abtflag = 0; return('A'); /* cause ABORT */ } /* Fold in bits 7,8 to compute */ cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */ if (cchksum == rchksum) { if (type == 'D') blockmv(oldpkt,data,*len); /* copy for reference */ return(type); /* OK return */ } ++badcrcs; /* count bad checksum */ if (list == 1) outc('C'); else if (list > 2) txtout(" Bad checksum "); return(FALSE); } /* end of rpack() */ servsend(type) /* send command to server-Kermit etc. */ char type; { int *len, *num; char pkt; switch(type) { case RMSV: /* Server Commands */ pkt = 'K'; /* packet-type */ goto Rmcont; case RMH: /* OS Commands */ pkt = 'C'; /* packet-type */ Rmcont: txtout(" Calling mainframe ... "); if (parex() == 0) { /* exchange parameters */ printmsg("Mainframe Kermit seems dead "); kmode = KERM; break; } else forever { printmsg(enter,"message"); if (keyline(packet) == 0) { kmode = CMND; break; } printmsg("Telling mainframe ... "); recsw(type,pkt); } break; case GET: /* fetch files */ printf(inform); printmsg(enter,"filenames"); if (keyline(packet) == 0) kmode = KERM; else { vtline(LOCMODE,rcvng); state = kmode = GET; } break; case SEND: /* send files */ vtline(LOCMODE,sendf); kmode = SEND; break; case BYE: /* logout from mainframe */ spack('G',n,1,"L"); /* generic logout */ kmode = KERM; outc(SP); txtout(trying); rpack(&len,&num,recpkt); if (len != 0) { recpkt[*len] = 0; printmsg("%s %s",mainsays,recpkt); } break; case LOGO: /* cancel mainframe Kermit */ spack('G',n,1,"F"); /* try "Finish" */ txtout(dots); if (rpack(&len,&num,recpkt) != 'Y') /* synchronize */ spack('E',0,strlen(errmsg),errmsg); vtline(LOCMODE,connto); kmode = CONN; break; case QUIT: /* cancel (local) Kermit */ kermkill(1); case MAIN: /* back to top level */ kmode = KERM; break; } /* end switch */ return; } /* end of servsend() */ setbaud() /* set line-speed from spdcode */ { vtline(LOCSPEED+3," "); vtline(LOCSPEED,spval[spdcode]); s4speed(spdcode); return; } /* end of setbaud() */ setpar() /* set parity from parity */ { commode &= 0xfcff; /* remove parity bits */ commode |= (int)parity * 256; /* substitute new */ s4set(commode,comctrl); return; } /* end of setpar() */ spack(type,num,len,data) /* Send a Packet */ char type, *data; int num, len; { int i; /* Character loop counter */ char c, chksum; register char *bufp; /* Buffer pointer */ static int cumnum = 0; if (list > 3) { /* Display outgoing packet */ outc(CR); printf(" Packet out: type %c, num %d, len %d:",type,num,len); outc(CR); if (len != 0) { data[len] = 0; printf(" data: \"%s\";",data); outc(CR); } } vtout(LOCOUT,type); vtout(LOCSEQ,tochar(n)); sprintf(work,"%d =",cumnum++); vtline(LOCPKTS,work); for (i=1; i<=pad; i++) if (nextout(&padchar) != 0) /* padding */ return; bufp = work; /* buffer pointer */ *bufp++ = SOH; *bufp++ = tochar(len+3); chksum = tochar(len+3); *bufp++ = tochar(num); chksum += tochar(num); typout = *bufp++ = type; chksum += type; for (i=0; i> 6)+chksum)&077; /* Compute final checksum */ *bufp++ = tochar(chksum); *bufp++ = eol; /* Extra-packet line terminator */ *bufp = CR; /* & CR for safety */ len = bufp-work+1; bufp = work; while (len-- > 0) if (nextout(*bufp++) != 0) break; vtout(LOCOUT,type|0x80); /* inverse of type */ if (netslow) /* discard any buffered dupes */ flushinput(); return; } /* end of spack() */ /********************** End of KLINE.C **************************/