PROGRAM Kermit(Input,Output); (*) * 29-Nov-83 Allow eight bit file transfer with SET EIGHT-BIT ON/OFF * add global flag and extra SET command [pgt001] * For byte value 0..255 the end of (data) string value is now -1, * and end of file value -2. * 1-Dec-83 Place all globals into module KermitGlobals. (*) IMPORTS Stdio FROM Stdio ; IMPORTS KermitGlobals FROM KermitGlobals ; (**********) IMPORTS KermitUtils FROM KermitUtils ; IMPORTS KermitParms FROM KermitParms ; IMPORTS KermitHelp FROM KermitHelp ; IMPORTS KermitError FROM KermitError ; IMPORTS KermitSend FROM KermitSend ; IMPORTS KermitRecv FROM KermitRecv ; IMPORTS Connect232 FROM Connect232 ; IMPORTS PMatch FROM PMatch ; IMPORTS PopCmdParse FROM PopCmdParse ; IMPORTS Perq_String FROM Perq_String ; IMPORTS Screen FROM Screen ; IMPORTS IO_Unit FROM IO_Unit ; IMPORTS IOErrors FROM IOErrors; IMPORTS IO_Others FROM IO_Others; IMPORTS System FROM System; IMPORTS Sleep FROM Sleep; (* Handle ^C's from the console -pt*) HANDLER CtlC ; BEGIN (*-CtlC-*) IOKeyClear ; (* Remove ^C from input stream *) CtrlCPending := False ; (* Clear to prevent next ^C from aborting job *) FromConsole := AbortNow (* Set our flag *) END ; (*-CtlC-*) HANDLER HelpKey(VAR str: Sys9s) ; (* Make the HELP key generate the correct command (i.e. not a switch) -pt*) BEGIN (*-HelpKey-*) str := 'HELP ' ; str[5] := Chr( CR ) END ; (*-HelpKey-*) PROCEDURE OverHd( p,f: Stats; VAR o:Integer); (* Calculate OverHead as % *) (* OverHead := (p-f)*100/f *) BEGIN IF (f = 0.0) THEN o := 0 ELSE o := Round( (p-f)*100/f ) END; PROCEDURE CalRat(f: Stats; t:Integer; VAR r:Integer); (* Calculate Effective Baud Rate *) (* Rate = f*10/t *) BEGIN IF (t = 0) THEN r := 0 ELSE r := Round( f*10/t ) END; PROCEDURE Statistics ; VAR overhead, effrate : Integer; BEGIN (*-Statistics-*) (* print info on number of packets etc *) (* All output here was originally to STDERR -pt*) Writeln ; Writeln('Packets sent: ',NumSendPacks:1); Writeln('Packets received: ',NumRecvPacks:1); (* Calculate overhead *) OverHd(ChInPack,ChInFile,overhead); IF (Overhead <> 0) THEN BEGIN Writeln('Overhead (%): ' ,overhead:1); END; IF (RunTime <> 0) THEN BEGIN (* calculate effective rate *) CalRat(ChInFile,RunTime,effrate); Writeln('Effective Rate: ',effrate:1); END; (* Transmit stats *) Inverse( TRUE ) ; Writeln(' Send :-') ; Inverse( FALSE ) ; Writeln('Number of ACK: ',NumACKrecv:1); Writeln('Number of NAK: ',NumNAKrecv:1); Writeln('Number of BAD: ',NumBADrecv:1); (* Transmit stats *) Inverse( TRUE ) ; Writeln(' Receive :-') ; Inverse( FALSE ) ; Writeln('Number of ACK: ',NumACK:1); Writeln('Number of NAK: ',NumNAK:1); Writeln END ; (*-Statistics-*) PROCEDURE FinishUp; (* do any End of Program clean up *) BEGIN Sclose(DiskFile); SYSfinish; (* do System dependent *) END; PROCEDURE DoConnect ; (* Connect to the other host -pt*) VAR whyExit: ConExitFlag ; (* Why "connect" exited *) ch: Char ; (* the character after the "escape" char *) BEGIN (*-DoConnect-*) Writeln('[Connecting to host. Type Control-', EscPrint, ' C or any button on the puck]') ; REPEAT whyExit := Connect( EscapeChar, HalfDuplex, TRUE) ; (* Get the command *) IF (whyExit = ConButtonExit) THEN (* the button was pressed *) BEGIN Nap( 10 ) ; ch := 'C' (* Close the connection *) END ELSE WHILE (IOCRead(TransKey, ch) <> IOEIOC) DO ; IF (ch = EscapeChar) THEN XmtChar( EscapeChar ) ELSE IF (ch = '?') THEN BEGIN Writeln ; Writeln('When CONNECT''ed to another host, type Control-', EscPrint) ; Writeln('followed by :-') ; Writeln(' C to close the connection') ; Writeln(' ^', EscPrint, ' to send that character') ; Writeln(' ? for this information') ; Writeln('[Back to host]') END (* help *) UNTIL (Uppercase(ch) = 'C') ; Writeln ; Writeln('[Connection closed. Returning to PERQ]') END ; (*-DoConnect-*) BEGIN StdIOInit; SYSinit; (* system dependent *) done:=False; Writeln ; REPEAT KermitInit; (* initialize *) WHILE NOT (RunType IN [transmit, receive, setparm]) AND (NOT done) DO BEGIN CmdIndex := GetCmdLine(NullIdleProc, 'Kermit-PQ', CmdLine, CmdSpelling, Inf, RECAST(MainMenu, pNameDesc), firstPress, OK_to_pop) ; ConvUpper( CmdSpelling ) ; (* Make it upper case *) (* see what the command was *) CASE CmdIndex OF 1: DoConnect ; (* CONNECT *) 2: done := True ; (* EXIT *) 3: DoHelp ; (* HELP *) 4: done := True ; (* QUIT *) 5: RunType := Receive ; (* RECEIVE *) 6: RunType := Transmit; (* SEND *) 7: RunType := SetParm ; (* SET *) 8: DoShow ; (* SHOW *) 9: Statistics ; (* STATISTICS *) 10: Writeln('%Not a KERMIT command: ', CmdSpelling) ; 11: Writeln('%Ambiguous command: ', CmdSpelling) ; 12: (* empty line *) ; 13: Writeln('%KERMIT does not take switches, type HELP.'); 14: Writeln('?Illegal character after command') ; (* ?? *) OTHERWISE: Writeln('?Unknown command: ', CmdSpelling) END (* case *) END; CASE RunType OF Receive: BEGIN (* filename is optional here *) (* Remove blanks from the cmd line *) IF (CmdLine <> '') THEN RemDelimiters( CmdLine, ' ', dumStr) ; IF GetArgument(aline) THEN BEGIN IF Exists(aline) AND FileWarning THEN BEGIN ErrorMsg('Overwriting: '); ErrorStr(aline); END; IF EightBitFile THEN (* [pgt001] *) DiskFile := Sopen(aline,StdIO8Write) ELSE DiskFile := Sopen(aline,StdIOWrite); IF (DiskFile <= StdIOError) THEN ErrorPack('Cannot Open File'); END; RecvSwitch; END; Transmit: BEGIN (* New version -pt*) (* must give file name, so ask if one was not given -pt*) IF (CmdLine = '') THEN BEGIN Write('File to transmit ', PromptChar) ; Readln( CmdLine ) (* get the response *) END ; (* What shall we do with the line ? *) (* First remove blanks *) RemDelimiters( CmdLine, ' ', dumStr) ; IF (CmdLine = '') THEN (* another empty line, do nothing *) ELSE IF IsPattern(CmdLine) THEN Writeln('%SEND does not take wild file names') ELSE SendSwitch (* SendFile checks parameters - file exists *) END; Invalid: (* nothing *); SetParm: SetParameters ; END; (* case *) UNTIL done; FinishUp; (* End of Program *) ScreenReset (* Clear up screen data *) END.