program kermit; (* $R-*) (* turn range checking off *) (* $L+*) USES {$u kermglob.code} kermglob, {$U kermutil.code} kermutil, (* {$U kermpack.code} kermpack, *) {$U parser.code} parser, {$U helper.code} helper, {$U sender.code} sender, {$U receiver.code} receiver; { Modifications by SP, 25 Oct 1983: adapt to IBM Version IV.1 Delete keyboard and serial buffering: provided by system already. Additional mods by SP, 18 Mar 1984: make all strings 255 chars long 13 May 84: Incorporate screen control through syscom record entries for portability } procedure showparms; forward; procedure connect; (* connect to remote host and transceive *) var ch: char; close: boolean; procedure read_esc; (* read character after esc char and interpret it *) begin repeat until read_ch(keyport,ch); (* wait until they've typed something in *) if (ch in ['a'..'z']) then (* uppercase it *) ch := chr(ord(ch) - ord('a') + ord('A')); if ch in ['B','C','S','?'] then case ch of 'B': sendbrk; (* B: send a break to the IBM *) 'C': close := true; (* C: end connection *) 'S': begin (* S: show status *) noun := allsym; showparms end; (* S *) '?': begin (* ?: show options *) writeln('B Send a BREAK signal.'); writeln('C Close Connection, return to KERMIT-UCSD command level.'); writeln('Q Query Status of connection'); writeln('F Send Control-F character to remote host.' ); writeln('S Send Control-S character to remote host.' ); writeln('? Print this list'); writeln('^',esc_char,' send the escape character itself to the'); writeln(' remote host.') end; (* ? *) end (* case *) else if ch = esc_char then (* ESC-char: send it out *) begin if half_duplex then begin write(ch); { changed from echo() by SP } write_ch(oport,ch) end (* if *) end (* else if *) else (* anything else: ignore *) write(chr(bell)) end; (* read_esc *) begin (* connect *) clear_buf(keyport); (* empty keyboard buffer *) clear_buf(inport); (* empty remote input buffer *) writeln('Connecting to host...type CTRL-',ctl(esc_char),' C to exit'); close := false; repeat if read_ch(inport,ch) then (* if char from host then *) echo(ch); (* echo it *) if read_ch(keyport,ch) then (* if char from keyboard then *) if ch <> esc_char then (* if not ESC-char then *) begin if half_duplex then (* echo it if half-duplex *) write(ch); { changed from echo() by sp } write_ch(oport,ch) (* send it out the port *) end (* if *) else (* ch = esc_char *) (* else is ESC-char so *) read_esc; (* interpret next char *) until close; (* if still connected, get more *) writeln('Disconnected') end; (* connect *) procedure fill_parity_array; (* parity value table for even parity...not(entry) = odd parity *) const min = 0; max = 126; var i, shifter, counter: integer; minch, maxch, ch: char; r: char_int_rec; begin minch := chr(min); maxch := chr(max); case parity of evenpar: for ch := minch to maxch do begin r.ch := ch; (* put char into variant record *) shifter := aand(r.i,255); (* mask off parity bit *) counter := 0; for i := 1 to 7 do begin (* count the 1's *) if odd(shifter) then counter := counter + 1; shifter := shifter div 2 end; (* for i *) if odd(counter) then (* stick a 1 on if necessary *) parity_array[ch] := chr(aor(ord(ch),128)) else parity_array[ch] := chr(aand(ord(ch),127)) end; (* for ch *) (* case even *) oddpar: for ch := minch to maxch do begin r.ch := ch; (* put char into variant record *) shifter := aand(r.i,255); (* mask off parity bit *) counter := 0; for i := 1 to 7 do begin (* count the 1's *) if odd(shifter) then counter := counter + 1; shifter := shifter div 2 end; (* for i *) if odd(counter) then (* stick a 1 on if necessary *) parity_array[ch] := chr(aand(ord(ch),127)) else parity_array[ch] := chr(aor(ord(ch),128)) end; (* for ch *) (* case odd *) markpar: for ch := minch to maxch do (* stick a 1 on all chars *) parity_array[ch] := chr(aor(ord(ch),128)); spacepar: for ch := minch to maxch do (* mask off parity on all chars *) parity_array[ch] := chr(aand(ord(ch),127)); nopar: for ch := minch to maxch do (* don't mess with parity bit at all *) parity_array[ch] := ch; end; (* case *) end; (* fill_parity_array *) $I setshow.text procedure initialize; var ch: char; begin pad := mypad; padchar := chr(mypchar); xeol := chr(my_eol); esc_char := chr(my_esc); quote := my_quote; ctlset := [chr(1)..chr(31),chr(del),quote]; half_duplex := false; debug := false; emulating := false; fwarn := false; spsiz := max_pack; rpsiz := max_pack; n := 0; parity := nopar; initvocab; fill_parity_array; ibm := false; xon := chr(17); bufpos := 1; bufend := 0; baud := defaultbaud; setup_comm end; (* initialize *) procedure closeup; begin page( output ) end; (* closeup *) begin (* main kermit program *) initialize; repeat write('Kermit-UCSD> '); readstr(keyport,line); case parse of unconfirmed: writeln('Unconfirmed'); parm_expected: writeln('Parameter expected'); ambiguous: writeln('Ambiguous'); unrec: writeln('Unrecognized command'); fn_expected: writeln('File name expected'); ch_expected: writeln('Single character expected'); null: case verb of consym: connect; helpsym: help; recsym: begin recsw(rec_ok); gotoxy(0,debugline); write(chr(bell)); if rec_ok then writeln('successful receive') else writeln('unsuccessful receive'); (*$I-*) (* set i/o checking off *) close(oldf); { why??? } if not rec_ok then close(f); { added by SP } (*$I+*) (* set i/o checking back on *) gotoxy(0,promptline); end; (* recsym *) sendsym: begin uppercase(xfilename); sendsw(send_ok); gotoxy(0,debugline); write(chr(bell)); if send_ok then writeln('successful send') else writeln('unsuccessful send'); (*$I-*) (* set i/o checking off *) close(oldf); (*$I+*) (* set i/o checking back on *) gotoxy(0,promptline); end; (* sendsym *) setsym: set_parms; show_sym: show_parms; end; (* case verb *) end; (* case parse *) until (verb = exitsym) or (verb = quitsym); closeup end. (* kermit *)