Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!rutgers!mit-eddie!genrad!decvax!ucbvax!ULKYVX.BITNET!RDROYA01 From: RDROYA01@ULKYVX.BITNET.UUCP Newsgroups: comp.sys.atari.st Subject: Uemail source (4 of 12) Message-ID: <8702052241.AA16292@ucbvax.Berkeley.EDU> Date: Thu, 5-Feb-87 06:24:00 EST Article-I.D.: ucbvax.8702052241.AA16292 Posted: Thu Feb 5 06:24:00 1987 Date-Received: Sat, 7-Feb-87 16:36:38 EST Sender: daemon@ucbvax.BERKELEY.EDU Organization: University of Louisville Lines: 1587 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # kermit.c # kertrans.c # kerrec.c # kertty.c # This archive created: Tue Feb 3 17:54:14 1987 cat << \SHAR_EOF > kermit.c /* kermit.c support routines and main entry point for Uemail file transfer * functions. Kermit send, receive, get, put, finish, and bye supported. * Buffer logging and direct ASCII transfer also available. All actions are * ASCII 7 bit files. Transfers are made into and out of Uemail buffers. */ #include #include #include #include "ed.h" #include "kermit.h" int emacsfile; /* if TRUE then \r become \n on ASCII transfers */ char getfiln[NFILEN]; /* name for remote file get or put */ char deflow[] = "XON/XOFF"; static unsigned char *tsr_ptr = (char *)0x00fffa2d; /* See St internals */ static long *hz_200 = (long *)0x000004ba; int *aaddress(); /* thanks Jwahar R. Bammi for this line A code */ int *aline_addr; /* Ptr to base of Aline variables */ int sav_row, sav_col; int flow = DEFLO; /* default flow control */ int defbaud = 7; int bps = DEFBPS; unsigned long *hpterm; /* HOST */ /* KERMIT CTRL command prompt for action and switch to appropriate state. * Returns TRUE on success. !TRUE on failures. Bound to ^_ and HELP on ST. */ kermit(flg, _n) register int flg, _n; { static char command[9]; /* command */ register char key; register int owf; owf = curwp->w_flag; /* save for redraw */ if ((_n=mlreply("Kermit-ST> ",command,8)) != TRUE) return(_n==FALSE ? FALSE : ABORT); /* Initialize these values */ /* Hope the first packet will get across OK */ eol = CR; /* EOL for outgoing packets */ quotech = '#'; /* Standard control-quote char "#" */ pad = 0; /* No padding */ padchar = '\0'; /* Use null if any padding wanted */ timint = DEFTIME; /* Default timeout */ parity = DEFPAR; /* Default to no parity */ logfile = 0; /* Capture flag */ emacsfile = 0; /* Trans to emacs (no EOF) */ en8quote(FALSE); key = tolower(command[0]); switch (key) { case 'b': /* B = Bye */ if(mlyesno("Logout remote")==TRUE) if(gencmdsw('L')==FALSE) { mlwrite("Remote does not ACK BYE"); (*term.t_beep)(); return(FALSE); } return(TRUE); /* No update */ case 'c': /* C = Connect command */ connect(); break; case 'e': /* E = transmit to GNU_EMACS command */ if(usebuffer(NULL,NULL) != TRUE) return(FALSE); gotobob(NULL, 1); update(); mlwrite("[Transmitting %s to remote EMACS]",curbp->b_bna me); emacsfile = 1; trans(); emacsfile = 0; connect(); break; case 'f': /* F = Finish */ if(gencmdsw('F')==FALSE) { mlwrite("Remote does not ACK FINISH"); (*term.t_beep)(); return(FALSE); } return(TRUE); /* No update */ case 'g': /* G = Get command */ if((_n=mlreply("Remote filename: ",getfiln,NFILEN))!=TRU E) return(_n); if(usebuffer(NULL,NULL) != TRUE) return(FALSE); gotoeob(NULL, 1); update(); if((_n=getsw()) == FALSE) { (*term.t_beep)(); mlreply("Get failed. Type ",command,2); } break; case 'l': /* L = Log session */ if(usebuffer(NULL,NULL) != TRUE) return(FALSE); gotoeob(NULL, 1); logfile = TRUE; connect(); break; case 'r': /* R = Receive command */ if(usebuffer(NULL,NULL) != TRUE) return(FALSE); gotoeob(NULL, 1); update(); if((_n=recsw()) == FALSE) { (*term.t_beep)(); mlreply("Receive failed. Type ",command,2); } break; case 'p': /* P = Put command */ if((_n=mlreply("Remote filename: ",getfiln,NFILEN))!=TRU E) return(_n); case 's': /* S = Send command */ if(usebuffer(NULL,NULL) != TRUE) return(FALSE); if (key == 's') strcpy(getfiln,curbp->b_bname); gotobob(NULL, 1); update(); if((_n=sendsw()) == FALSE) { if (key == 's') mlwrite("Send failed"); else mlwrite("Put failed"); (*term.t_beep)(); } if (key == 's') connect(); break; case 't': /* T = transmit command */ if(usebuffer(NULL,NULL) != TRUE) return(FALSE); gotobob(NULL, 1); update(); mlwrite("[Transmitting: %s]",curbp->b_bname); trans(); connect(); break; default: mlwrite("Connect, Send, Receive, Get, Put, Finish, Bye\ , Log, Transfer"); return(FALSE); } /* Restore controlling tty's modes */ owf |= WFHARD; owf |= WFMODE; curwp->w_flag |= owf; sgarbf = TRUE; /* we know screen is garbage after connect */ update(); return(TRUE); } /* * c o n n e c t * * Establish a virtual terminal connection with the remote host, over an * assigned tty line. */ connect() { register int c; setterm(REMOTE); while (1) { if (Bconstat(2)) if(readcon() == FALSE) break; if (Bconstat(1)) { c=readaux(); ttputc(c); if (logfile) { if (c=='\n') { lnewline(); continue; } if (c=='\r') continue; linsert(1,c); } } } setterm(HOST); return(FALSE); } /* set up terminal's screen and allow it to be saved for later. */ setterm(f) int f; { static char scrbase[0x7d10]; static unsigned char firsttime = TRUE; extern int deskcol; if (hpterm == NULL) hpterm = Physbase(); /* init TERM screen address */ if (f == REMOTE) { Bconout(2,0x1b); /* disable cursor */ Bconout(2,'f'); copy(scrbase,hpterm,0x7d00); if (firsttime) { aline_addr = aaddress(); Bconout(2,0x1b); /* clear screen */ Bconout(2,'E'); showhelp(); sav_row = aline_addr[-13];/* save cursor position */ sav_col = aline_addr[-14]; Rsconf(defbaud,flow,-1,-1,-1,-1); mtwrite("[%s active at %dbps]",deflow,bps); firsttime = FALSE; } (*term.t_move)(sav_row,sav_col); Bconout(2,0x1b); /* enable cursor */ Bconout(2,'e'); return(TRUE); } else if (f == HOST) { sav_row = aline_addr[-13]; /* save cursor position */ sav_col = aline_addr[-14]; Bconout(2,0x1b); /* disable cursor */ Bconout(2,'f'); copy(hpterm,scrbase,0x7d00); ttopen(); /* restore uemail screen */ Bconout(2,0x1b); /* enable cursor */ Bconout(2,'e'); return(TRUE); } else if (f == SHOWHELP) { sav_row = aline_addr[-13]; /* save cursor position */ sav_col = aline_addr[-14]; Bconout(2,0x1b); /* disable cursor */ Bconout(2,'f'); copy(hpterm,scrbase,0x7d00); /* save current screen */ showhelp(); /* write help message */ while(ttgetc()) /* wait for */ if (scancode == 0x62) /* HELP key */ break; copy(scrbase,hpterm,0x7d00); /* restore old screen */ (*term.t_move)(sav_row,sav_col); Bconout(2,0x1b); /* enable cursor */ Bconout(2,'e'); return(TRUE); } } /* * return the base address of the line A variables * Bammi @ Case */ int * aaddress() { asm("dc.w $A000");/* Line A trap - 0000 is init line-A */ /* d0 and a0 now contain the address * so we can just return and the result * will be valid */ } /* a mini-mlwrite for the terminal mode */ /* VARARGS */ mtwrite(fmt,arg1,arg2,arg3,arg4) register char *fmt; register long arg1,arg2,arg3,arg4; { static char buf[128]; sprintf(buf,fmt,arg1,arg2,arg3,arg4); ttputc(0x1b);ttputc('j'); /* save cursor */ (*term.t_move)(term.t_nrow,0); ttputc(0x1b);ttputc('l'); /* delete line */ Cconws(buf); ttputc(0x1b);ttputc('k'); /* restore cursor */ return(TRUE); } /* A modicum of help for the RS232 connection module */ int showhelp() { register int i; i = 5; Crawio(0x1b); Crawio('p'); /* rev video on */ (*term.t_move)(i++,17); Cconws(" "); (*term.t_move)(i++,17); Cconws(" ALT-UNDO return to Uemail "); (*term.t_move)(i++,17); Cconws(" ALT-B set the baud rate "); (*term.t_move)(i++,17); Cconws(" ALT-C change color "); (*term.t_move)(i++,17); Cconws(" ALT-E load an alias file "); (*term.t_move)(i++,17); Cconws(" ALT-L load a macro file "); (*term.t_move)(i++,17); Cconws(" ALT-O turn off flow control "); (*term.t_move)(i++,17); Cconws(" ALT-R turn on RTS/CTS "); (*term.t_move)(i++,17); Cconws(" ALT-X turn on XON/XOFF "); (*term.t_move)(i++,17); Cconws(" ALT-T show the current time "); (*term.t_move)(i++,17); Cconws(" ALT-CTRL-B send a break "); (*term.t_move)(i++,17); Cconws(" ALT-CTRL-C run a program "); (*term.t_move)(i++,17); Cconws(" ALT-? this help message "); (*term.t_move)(i++,17); Cconws(" HELP this help message "); (*term.t_move)(i++,17); Cconws(" \r\n"); Crawio(0x1b); Crawio('q'); /* rev video off */ return(TRUE); } /* setbaud for RS232 (default is 1200) */ int setbaud() { register int c; mtwrite("Baud rate [a/b/c/d/e] a = 300, \ b = 1200, c = 2400, d = 9600, e = 19,200"); c = ttgetc(); switch(c) { case 'a': case 'A': defbaud = 9; bps = 300; Rsconf(defbaud,flow,-1,-1,-1,-1); mtwrite("[Baud = %dbps]",bps); return(TRUE); case 'b': case 'B': defbaud = 7; bps = 1200; Rsconf(defbaud,flow,-1,-1,-1,-1); mtwrite("[Baud = %dbps]",bps); return(TRUE); case 'c': case 'C': defbaud = 4; bps = 2400; Rsconf(defbaud,flow,-1,-1,-1,-1); mtwrite("[Baud = %dbps]",bps); return(TRUE); case 'd': case 'D': defbaud = 1; bps = 9600; Rsconf(defbaud,flow,-1,-1,-1,-1); mtwrite("[Baud = %dbps]",bps); return(TRUE); case 'e': case 'E': defbaud = 0; bps = 19200; Rsconf(defbaud,flow,-1,-1,-1,-1); mtwrite("[Baud = %dbps]",bps); return(TRUE); default: Rsconf(defbaud,flow,-1,-1,-1,-1); mtwrite("[Baud = %dbps]",bps); return(TRUE); } } /* * KERMIT utilities. */ /* generic command for BYE and FINish */ gencmdsw(cmd) char cmd; { int num, len; /* Packet number, length */ packet[0] = cmd; /* Generic command */ spack('G', 0, 1, packet); /* Send Generic command */ switch(rpack(&len,&num,packet)) /* Get packet */ { case 'Y': return(TRUE); case 'E': prerrpkt(packet); return(FALSE); default: return(FALSE); } } /* * b u f i l l * * Get a bufferful of data from the buffer that's being sent. * Only control-quoting and 8-bit quoting is done; * repeat count prefixes are not handled. */ bufill(buffer) char buffer[]; /* Buffer */ { register char t; /* Char read from file */ register char *buffend; /* End of buffer pointer */ register char *buffp; /* Pointer into buffer */ register int unprintable; /* Is a character printable ?*/ short eolflag = FALSE; /* kludge for VAX */ buffend = &buffer[spsiz-9]; /* set up end of buffer pointer */ buffp=buffer; /* and the current position */ while(curwp->w_dotp != curbp->b_linep) { t = lgetc(curwp->w_dotp, curwp->w_doto); if (curwp->w_doto == llength(curwp->w_dotp)) { t = eol; eolflag = TRUE; /* kludge for VAX */ } unprintable = ((t=buffend) /* this is how you avoid pointer */ return((int)buffp-(int)buffer); /* subtraction */ } /* not (int)(buffp-buffer) */ if (buffp == buffer) return(EOF); return((int)buffp-(int)buffer); /* Handle partial buffer */ } /* * b u f e m p * * Put data from an incoming packet into the default buffer. */ bufemp(buffer,len) char buffer[]; /* Buffer */ int len; /* Length */ { register int i; /* Counter */ register char t; /* Character holder */ register int highbit; /* place to hold quoted highbit */ highbit = 0; for (i=0; i= 32000) /* time is up */ return(FALSE); return ((int)Bconin(1)); /* char not masked when read */ } sauxstr(buf,len) char *buf; int len; { for(;len>0;len--) sendaux(*buf++); } sendaux(c) int c; { while(!Bcostat(1)) { if (Bconstat(2)) if (ttgetc()==0x07) return(FALSE); } Bconout(1,c); /* Send character */ } /* * p r e r r p k t * * Print contents of error packet received from remote host. */ prerrpkt(msg) char *msg; { mlwrite("ABORT: %s",msg); return; } en8quote(t) int t; { qflag = t; /* no binary files allowed */ } /* tsr_ptr points to the 8 bit TSR register of the 68901 * From Jwahar R. Bammi * send a break * Modifies Bit 3 in the TSR (reg 23) of the Mfp */ sendbrk() { register long save_ssp; register long time; save_ssp = Super(0L); /* Super Mode */ /* set bit 3 of the TSR */ *tsr_ptr |= (unsigned char)8; /* wait for 250 ms -- you can adjust the duration * 250 ms seems to be almost a universal figure for break * duration. */ time = *hz_200 + 50; while(*hz_200 < time) /* wait */ ; /* reset bit 3 of the tsr */ *tsr_ptr &= (unsigned char)~8; Super(save_ssp); /* Back to user Mode */ } /* * f l u s h i n p u t * * Dump all pending input to clear stacked up NACK's. */ flushinput() { /* TOS Clear AUX receive buffer */ while (Cauxis()) Cauxin(); } SHAR_EOF cat << \SHAR_EOF > kertrans.c /* 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" */ } } SHAR_EOF cat << \SHAR_EOF > kerrec.c /* 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 */ } SHAR_EOF cat << \SHAR_EOF > kertty.c #include #include #include #include "ed.h" #include "kermit.h" #ifndef ESC #define ESC 0x1b #endif #ifndef DEL #define DEL 0x7f #endif extern int *aline_addr; /* Ptr to base of Aline variables */ extern int sav_row, sav_col; typedef struct MACTAB { struct MACTAB *m_fmac; /* next MACTAB */ short *keymac; /* pointer to the macro */ char key; /* the key */ } MACTAB; /* Do a direct read of the console. The present scheme does not always * work with a minimal NULL modem (i.e. only lines 1,2,&3 connected). */ readcon() { register int c,i; extern MACTAB *mheadp, *mcralloc(); register MACTAB *mt; char fname[16]; extern char *getfname(); extern short getktpcode(); c=getkkey(); /* Read the keyboard and get mask */ if (c == '`') /* keyboard macro */ { c = (*term.t_getchar)(); if (c == '`') { sendaux('`'); return(TRUE); } if (mheadp==NULL || mheadp->m_fmac == NULL) { mtwrite("No defineable macros assigned"); return(TRUE); } if((mt=mcralloc(FALSE,c))!= (MACTAB *)NULL) sendmacro(mt->keymac); } else if (shiftstatus == 12 && scancode == 0x30) /* CTRL-ALT-B */ sendbrk(); else if (shiftstatus == 12 && scancode == 0x2e) /* CTRL-ALT-C */ { setterm(HOST); shell(FALSE,HUGE); setterm(REMOTE); } else if (shiftstatus == 17 || shiftstatus == 18) /* C-Lock + Shift */ { i=tolower(c); sendaux(i); } else if (shiftstatus == 0 && scancode == 0x62) /* HELP Key */ setterm(SHOWHELP); else if (shiftstatus == 8) /* ALT key pressed */ { switch(scancode) { case 0x12: /* E */ /* save cursor position */ sav_row = aline_addr[-13]; sav_col = aline_addr[-14]; commfil(TRUE,TRUE); ttopen(); /* update color */ (*term.t_move)(sav_row,sav_col); return(TRUE); case 0x61: /* UNDO */ return(FALSE); case 0x2e: /* C */ /* save cursor position */ sav_row = aline_addr[-13]; sav_col = aline_addr[-14]; paintbuffer(TRUE,TRUE); (*term.t_move)(sav_row,sav_col); return(TRUE); case 0x30: /* B */ return(setbaud()); case 0x26: /* L */ sav_row = aline_addr[-13]; sav_col = aline_addr[-14]; loadmac(TRUE); (*term.t_move)(sav_row,sav_col); return(TRUE); case 0x18: /* O */ /* Turn off flow control */ flow = NOFLO; Rsconf(-1,flow,-1,-1,-1,-1); mtwrite("[Handshaking disabled]"); return(TRUE); case 0x13: /* R */ flow = RTS; Rsconf(-1,flow,-1,-1,-1,-1); mtwrite("[RTS/CTS active]"); return(TRUE); case 0x14: showtime(TRUE,HUGE); return(TRUE); case 0x2d: /* X */ flow = XON; Rsconf(-1,flow,-1,-1,-1,-1); mtwrite("[XON/XOFF active]"); return(TRUE); case 0x35: /* / ? */ setterm(SHOWHELP); return(TRUE); default: sendaux(c); return(TRUE); } } else { if (c & SPEC) if (getfname(c,fname)!=(char *)NULL) c = (int)getktpcode(fname); if (c & META) { i = c & ~META; sendaux(ESC); c = i; } if (c & CTLX) { i = c & ~CTLX; sendaux(0x18); c = i; } if (c & CTRL) { i = c & ~CTRL; c = i - '@'; } sendaux(c); } return(TRUE); } /* pratically identical to getkey in main.c but that one uses mlwrite * which would damage the terminal screen when it tried to update. */ getkkey() { register int c; extern char keyscan[]; c = (*term.t_getchar)(); #if ST if (scancode == 0x70 && shiftstatus != 16) return (CTRL|'X'); #endif if (c == DEL) return(c); if (c == METACH) { /* Apply M- prefix */ mtwrite("Meta: "); c = (*term.t_getchar)(); return (META | c); } #if ST /* use special keys or number pad (code >= 0x63) ? * 0x03 = scancode for ^@ (setmark). */ if ((c == NULL && scancode != 0x03) || scancode >= 0x4a) if (scancode > 0x32) { /* if CapsLock and number pad, use real numbers */ if (shiftstatus == 16 && (scancode > 0x62 || scancode == 0x4a || scancode == 0x4e)) return(c); else return (SPEC | scancode); } else { c = keyscan[scancode]; return (META | c); } #endif if (c>=0x00 && c<=0x1F) /* C0 control -> C- */ c = CTRL | (c+'@'); return (c); } /* Allows keyboard macros to go through completely on a slow and noisy line */ sendmacro(buf) register short *buf; { register int c; char fname[16]; while(*buf != (CTLX|')')) { while(!(int)Cauxos()) /* wait for line to clear */ ; if (*buf & SPEC) if (getfname(*buf,fname)!=(char *)NULL) *buf = (int)getktpcode(fname); if (*buf & META) { c = *buf & ~META; sendaux(ESC); *buf = c; } if (*buf & CTLX) { c = *buf & ~CTLX; sendaux(0x18); *buf = c; } if (*buf & CTRL) { c = *buf & ~CTRL; *buf = c - '@'; } sendaux(*buf++); } } SHAR_EOF # End of shell archive exit 0 %NONAME-W-NOMSG, Message number 00000000