home *** CD-ROM | disk | FTP | other *** search
- { Software Tools in PASCAL -- Procedures used by KERMIT }
- { Also Externals called by Send & Receive Switch }
-
- {$E+}
-
- PROCEDURE stiphalt; { used by external procedures for halt }
- EXTERNAL;
-
- PROCEDURE FinishUp(t:boolean);
- EXTERNAL;
-
- PROCEDURE PutBin(c : character); { Output Binary }
- BEGIN
- IF (c = ENDFILE)
- THEN
- { flush buffer}
- { fill with NULLS -- will be written below }
- WHILE (bptr <= BLKSIZE) DO
- BEGIN
- binbuffer[bptr] := chr(NULLCHAR);
- bptr := bptr + 1;
- END;
-
- IF bptr > BLKSIZE
- THEN
- BEGIN
- bfile^ := binbuffer;
- put(bfile);
- bptr := 1;
- IF c <> ENDFILE THEN
- putbin(c);
- END
- ELSE
- BEGIN
- binbuffer[bptr] := chr(c);
- bptr := bptr + 1;
- END
- END;
-
-
-
- { close (omsi) -- close a file }
- PROCEDURE Sclose (fd : filedesc);
- BEGIN
- IF (fd >= STDERR) AND (fd <= MAXOPEN)
- THEN
- BEGIN
- WITH openlist[fd] DO
- BEGIN
- IF (mode <= -IOREAD)
- THEN
- BEGIN
- IF (mode = -IOWRITE)
- THEN
- putbin(ENDFILE);
- { flush buffer }
- close(bfile);
- mode := IOERROR;
- END
- ELSE
- BEGIN
- close(filevar);
- mode := IOAVAIL;
- END
- END;
- END
- END;
-
-
- PROCEDURE ResetLine; { Reset DL11 Line }
- EXTERNAL;
-
-
- PROCEDURE ConUP; { Console upper case only }
- EXTERNAL;
-
- { close all files on exit }
- PROCEDURE closeall;
- VAR
- fd : filedesc;
- BEGIN
- FOR fd := STDERR TO MAXOPEN DO
- Sclose(fd);
- ResetLine;
- ConUP;
- END;
-
-
-
- { Open file in Binary Mode }
- FUNCTION Obinary (VAR intname : string100; omode : integer) : filedesc;
- VAR
- len : integer;
- BEGIN
- IF (omode = -IOREAD)
- THEN
- BEGIN
- reset(bfile, intname,'',len);
- binbuffer := bfile^;
- bptr := 1;
- END
- ELSE
- BEGIN
- rewrite(bfile, intname);
- bptr := 1;
- END;
- IF (omode = -IOREAD) AND (len <= 0)
- THEN
- BEGIN
- sclose(BINARYFILE);
- Obinary := IOERROR;
- END
- ELSE
- BEGIN
- Obinary := BINARYFILE;
- openlist[BINARYFILE].mode := omode;
- END;
- END;
-
-
- { open (RT-11) -- open a file for reading or writing }
- FUNCTION Sopen (VAR name : string; omode : integer) : filedesc;
- VAR
- i ,len: integer;
- intname : string100;
- found : boolean;
- BEGIN
- i := 1;
- WHILE (name[i] <> ENDSTR) AND (name[i] <> NEWLINE) DO
- BEGIN
- intname[i] := chr(name[i]);
- i := i + 1
- END;
-
- FOR i := i TO MAXSTR DO
- intname[i] := ' '; { pad name with blanks }
-
- IF (omode < IOERROR)
- THEN
- Sopen := obinary(intname,omode)
- ELSE
- BEGIN
-
- { find a free slot in openlist }
- Sopen := IOERROR;
- found := false;
- i := 1;
- WHILE (i <= MAXOPEN) AND (NOT found) DO
- BEGIN
- IF (openlist[i].mode = IOAVAIL)
- THEN
- WITH openlist[i] DO
- BEGIN
- mode := omode;
- IF (mode = IOREAD)
- THEN
- reset(filevar, intname,'',len)
- ELSE
- IF (mode = IOWRITE)
- THEN
- rewrite(filevar, intname);
-
- IF (len <= 0) AND (mode=IOREAD)
- THEN
- BEGIN
- Sclose(i);
- Sopen := IOERROR
- END
- ELSE
- Sopen:=i;
-
- found := true
- END;
- i := i + 1
- END
- END
- END;
-
- { getcf (UCB) -- get one character from file }
- FUNCTION getcf (VAR c: character; fd : filedesc) : character;
- FORWARD;
-
- { getc (UCB) -- get one character from standard input }
- FUNCTION getc (VAR c : character) : character;
- VAR
- ch : char;
- BEGIN
- IF (redirect[STDIN] = STDIN )
- THEN
- BEGIN
- IF eof
- THEN
- c := ENDFILE
- ELSE
- IF eoln
- THEN
- BEGIN
- readln;
- c := NEWLINE
- END
- ELSE
- BEGIN
- read(ch);
- c := ord(ch)
- END;
- getc := c
- END
- ELSE
- getc := getcf(c,redirect[STDIN])
- END;
-
-
- PROCEDURE GETCL(VAR c : character;VAR t :integer);
- { Get Character from DL11 Line }
- { TimeLeft is also used }
- EXTERNAL;
-
- PROCEDURE GetBin(VAR c: character); { Get Binary character }
- BEGIN
- IF bptr > BLKSIZE
- THEN
- BEGIN
- get(bfile);
- binbuffer := bfile^;
- IF eof(bfile)
- THEN
- c := ENDFILE
- ELSE
- BEGIN
- bptr := 1;
- getbin(c);
- END;
- END
- ELSE
- BEGIN
- c := ord(binbuffer[bptr]);
- bptr := bptr + 1;
- END
- END;
-
- FUNCTION getcf; { Get Character from file }
- VAR
- ch : char;
- BEGIN
- IF (fd = STDIN)
- THEN
- getcf := getc(c)
- ELSE WITH openlist[fd] DO
- IF (mode = IOLINE)
- THEN
- BEGIN
- GETCL(c,TimeLeft);
- { strip parity }
- IF (parity <> oNONE) THEN
- c := c AND 177B;
- END
- ELSE
- IF (mode = -IOREAD)
- THEN
- GETBIN(c)
- ELSE
- IF eof(filevar)
- THEN
- c := ENDFILE
- ELSE
- IF eoln(filevar)
- THEN
- BEGIN
- readln(filevar);
- c := NEWLINE
- END
- ELSE
- BEGIN
- read(filevar, ch);
- c := ord(ch)
- END;
- getcf := c
- END;
-
- { getline (UCB) -- get a line from file }
- FUNCTION getline (VAR s : string; fd : filedesc;
- maxsize : integer) : boolean;
- VAR
- i : integer;
- c : character;
- BEGIN
- i := 1;
- REPEAT
- s[i] := getcf(c, fd);
- i := i + 1
- UNTIL (c = ENDFILE) OR (c = NEWLINE) OR (i >= maxsize);
- IF (c = ENDFILE)
- THEN { went one too far }
- i := i - 1;
- s[i] := ENDSTR;
- getline := (c <> ENDFILE)
- END;
-
- { putcf (UCB) -- put a single character on file fd }
- PROCEDURE putcf (c : character; fd : filedesc);
- FORWARD;
-
- { putc (UCB) -- put one character on standard output }
- PROCEDURE putc (c : character);
- BEGIN
- IF (redirect[STDOUT] = STDOUT)
- THEN
- IF c = NEWLINE
- THEN
- writeln
- ELSE
- write(chr(c))
- ELSE
- putcf(c,redirect[STDOUT]);
- END;
-
- PROCEDURE PUTCL(VAR c : character); { Output character to DL11 Line }
- EXTERNAL;
-
- PROCEDURE putcf; { Put character to file }
- BEGIN
- IF (fd = STDOUT)
- THEN
- putc(c)
- ELSE WITH openlist[fd] DO
- IF (mode = IOLINE)
- THEN
- PUTCL(c)
- ELSE
- IF (mode = -IOWRITE)
- THEN
- PUTBIN(c)
- ELSE
- IF c = NEWLINE
- THEN
- writeln(filevar)
- ELSE
- write(filevar, chr(c))
- END;
-
- { putstr (UCB) -- put out string on file }
- PROCEDURE putstr (VAR s : string; f : filedesc);
- VAR
- i : integer;
- BEGIN
- i := 1;
- WHILE (s[i] <> ENDSTR) AND (i < MAXSTR) DO
- BEGIN
- putcf(s[i], f);
- i := i + 1
- END
- END;
-
- PROCEDURE Xbreak(VAR f : text);
- { As External since break is already defined }
- EXTERNAL;
-
-
- PROCEDURE Obreak(fd : filedesc);
- BEGIN
- IF (fd = STDOUT)
- THEN
- Xbreak(output)
- ELSE
- Xbreak(openlist[fd].filevar);
- END;
-
- PROCEDURE GTLINE(var commandLine : string80);
- BEGIN
- write('KERMIT-RT> ');
- Obreak(STDOUT);
- readln(commandLine);
- END;
-
-
- { itoc - convert integer n to char string in s[i]... }
- FUNCTION itoc (n : integer; VAR s : string; i : integer) : integer;
- { returns end of s }
- BEGIN
- IF (n < 0)
- THEN
- BEGIN
- s[i] := ord('-');
- itoc := itoc(-n, s, i+1)
- END
- ELSE
- BEGIN
- IF (n >= 10)
- THEN
- i := itoc(n DIV 10, s, i);
- s[i] := n MOD 10 + ord('0');
- s[i+1] := ENDSTR;
- itoc := i + 1
- END
- END;
-
- { length -- compute length of string }
- FUNCTION length (VAR s : string) : integer;
- VAR
- n : integer;
- BEGIN
- n := 1;
- WHILE (s[n] <> ENDSTR) DO
- n := n + 1;
- length := n - 1
- END;
-
- { scopy -- copy string at src[i] to dest[j] }
- PROCEDURE scopy (VAR src : string; i : integer;
- VAR dest : string; j : integer);
- BEGIN
- WHILE (src[i] <> ENDSTR) DO
- BEGIN
- dest[j] := src[i];
- i := i + 1;
- j := j + 1
- END;
- dest[j] := ENDSTR
- END;
-
- { index -- find position of character c in string s }
- FUNCTION index (VAR s : string; c : character) : integer;
- VAR
- i : integer;
- BEGIN
- i := 1;
- WHILE (s[i] <> c) AND (s[i] <> ENDSTR) DO
- i := i + 1;
- IF (s[i] = ENDSTR)
- THEN
- index := 0
- ELSE
- index := i
- END;
-
-
- PROCEDURE CtoS({ Using } x:cstring; { Returning } VAR s:string);
- { convert constant to STIP string }
- VAR
- i : integer;
- BEGIN
- FOR i:=1 TO CONLENGTH DO
- s[i] := ord(x[i]);
- s[CONLENGTH+1] := ENDSTR;
- END;
-
-
- FUNCTION Exists({ Using }VAR s:string): { Returning } boolean;
- { returns true if file exists }
- VAR
- fd: filedesc;
- result: boolean;
- BEGIN
- fd := Sopen(s,IOREAD);
- result := (fd <> IOERROR);
- Sclose(fd);
- Exists := result;
- END;
-
-
-
- FUNCTION nargs: integer; { returns number arguments }
- { for RT - 11 }
- BEGIN
- nargs := cmdargs
- END;
-
-
- FUNCTION getarg(n:integer;VAR s:string;maxsize:integer): BOOLEAN;
- { return the nth argument }
- { RT - 11 }
- BEGIN
- IF ((n<1) OR (cmdargs<n))
- THEN
- getarg := false
- ELSE
- BEGIN
- scopy(cmdlin,cmdidx[n],s,1);
- getarg := true
- END;
- END;
-
-
- PROCEDURE PutCon({ Using } x:cstring;
- { Using } fd:filedesc);
- { output literal }
- VAR
- s: string;
- BEGIN
- CtoS(x,s);
- putstr(s,fd);
- obreak(fd);
- END;
-
- PROCEDURE PutCln({ Using } x:cstring;
- { Using } fd:filedesc);
- { output literal followed by NEWLINE }
- BEGIN
- PutCon(x,fd);
- putcf(NEWLINE,fd);
- obreak(fd);
- END;
-
- PROCEDURE PutNum({ Using } n:integer;
- { Using } fd:filedesc);
- { Ouput number }
- VAR
- s: string;
- dummy: integer;
- BEGIN
- s[1] := BLANK;
- dummy := itoc(n,s,2);
- putstr(s,fd);
- obreak(fd);
- END;
-
- PROCEDURE PutCS({ Using } x:cstring;
- { Using } s : string;
- { Using } fd:filedesc);
- { output literal & string }
- BEGIN
- PutCon(x,fd);
- putstr(s,fd);
- putcf(NEWLINE,fd);
- obreak(fd);
- END;
-
- PROCEDURE PutCN({ Using } x:cstring;
- { Using } v : integer;
- { Using } fd:filedesc);
- { output literal & number }
- BEGIN
- PutCon(x,fd);
- PutNum(v,fd);
- putcf(NEWLINE,fd);
- obreak(fd);
- END;
-
- { For KERMIT }
-
- PROCEDURE AddTo({ Updating } VAR sum : Stats;
- { Using } inc:integer);
- BEGIN
- sum := sum + inc;
- END;
-
-
-
- PROCEDURE PutPacket( p : Ppack); { Output Packet }
- VAR
- i : integer;
- BEGIN
- IF (Pad >0)
- THEN
- FOR i := 1 TO Pad DO
- putcf(PadChar,LineOut);
- WITH p^ DO
- BEGIN
- putcf(mark,LineOut);
- putcf(count,LineOut);
- putcf(seq,LineOut);
- putcf(ptype,LineOut);
- putstr(data,LineOut);
- END;
- END;
-
- FUNCTION GetIn { Returning } :character; { get character }
- { Should return NULL ) if no characters }
- VAR
- c :character;
- BEGIN
- c := getcf(c,LineIn);
- GetIn := c;
-
- IF (RunType = Receive) AND (c <> NULLCHAR)
- THEN
- AddTo(ChInPackRecv,1);
-
- END;
-
-
- PROCEDURE StartTimer;
- BEGIN
- TimeLeft := TheirTimeOut * 60; { in ticks }
- END;
-
- PROCEDURE StopTimer;
- BEGIN
- TimeLeft := MaxInt; { * 60 }
- END;
-
- FUNCTION MakeChar({ Using } c:character): { Returning } character;
- { convert integer to printable }
- BEGIN
- MakeChar := c + BLANK;
- END;
-
- FUNCTION UnChar({ Using } c:character): { Returning } character;
- { reverse of makechar }
- BEGIN
- UnChar := c - BLANK
- END;
-
-
- FUNCTION IsControl( c:character): boolean;
- { true if control }
- BEGIN
- { assume -128 .. 127 for characters }
- IF (c >= NULLCHAR)
- THEN
- IsControl := (c=DEL ) OR (c < BLANK )
- ELSE
- IsControl := IsControl(c + 128);
- END;
-
-
-
- FUNCTION Ctl( c:character): character;
- { c XOR 100 }
- BEGIN
- { assume -128 .. 127 for characters }
- IF (c >= NULLCHAR)
- THEN
- IF (c < 64)
- THEN
- c := c + 64
- ELSE
- c := c - 64
- ELSE
- c := Ctl(c + 128) - 128;
- Ctl := c;
- END;
-
-
- FUNCTION CheckFunction({ Using } c:integer): { Returning } character;
- { calculate checksum }
- VAR
- x: integer;
- BEGIN
- { CheckFunction := (c + ( c AND 300 ) /100 ) AND 77; }
- x := (c MOD 256 ) DIV 64;
- x := x + c;
- CheckFunction := x MOD 64;
- END;
-
- PROCEDURE EnCodeParm({ Updating } VAR data:string); { encode parameters }
- VAR
- i: integer;
- BEGIN
- FOR i:=1 TO NUMPARAM DO
- data[i] := BLANK;
- data[NUMPARAM+1] := ENDSTR;
- data[1] := MakeChar(SizeRecv); { my biggest packet }
- data[2] := MakeChar(MyTimeOut); { when I want timeout}
- data[3] := MakeChar(MyPad); { how much padding }
- data[4] := Ctl(MyPadChar); { my padding character }
- data[5] := MakeChar(myEOL); { my EOL }
- data[6] := MyQuote; { my quote char }
-
- { Handle 8 Bit Quoting - for transmit use our default }
-
- IF RunType = Transmit
- THEN
- data[7] := Def8QuoteMode { Default mode }
- ELSE
- { For receive -- these may have to be changed }
- IF (QuoteForBinary = TYPEY) THEN
- IF (Def8QuoteMode <> TYPEY) THEN
- BEGIN
- BinaryMode := Quoted;
- data[7] := DEF8CHAR;
- QuoteForBinary := DEF8CHAR;
- END
- ELSE
- BEGIN
- BinaryMode := FullBinary;
- data[7] := TYPEY;
- END
- ELSE IF (QuoteForBinary = TYPEN) THEN
- data[7] := TYPEY
- ELSE IF (QuoteForBinary = BLANK) THEN
- data[7] := BLANK
- ELSE
- data[7] := TYPEY;
-
- { Make sure that Quote Character is OK }
- IF (RunType = Receive) AND (BinaryMode <> Quoted)
- THEN
- QuoteForBinary := ENDSTR;
-
- END;
-
- PROCEDURE DeCodeParm({ Using } VAR data:string); { decode parameters }
- VAR
- i,l : integer;
- BEGIN
- l := length(data);
- IF l < NUMPARAM
- THEN
- FOR i := l + 1 TO NUMPARAM DO
- data[i] := BLANK;
- data[NUMPARAM+1] := ENDSTR;
- SizeSend := UnChar(data[1]); { Packet Size }
- TheirTimeOut := UnChar(data[2]); { when I should time out }
- Pad := UnChar(data[3]); { padding characters to send }
- PadChar := Ctl(data[4]); { padding character }
- IF data[5] = BLANK
- THEN SendEOL := CR
- ELSE SendEOL := UnChar(data[5]);{ EOL to send }
- IF data[6] = BLANK
- THEN SendQuote := SHARP
- ELSE SendQuote := data[6]; { quote to send }
- QuoteForBinary := data[7]; { 8 Bit Quote Character }
-
- { Change these if Full Binary not available }
- { Use NotSupported if 'N' received }
-
- IF QuoteForBinary = TYPEY THEN
- BinaryMode := FullBinary
- ELSE IF QuoteForBinary = BLANK THEN
- BinaryMode := FullBinary
- ELSE IF QuoteForBinary = TYPEN THEN
- BinaryMode := NotSupported
- ELSE
- BinaryMode := Quoted;
-
- { Set it to quoted if we asked for it }
- IF (RunType = Transmit) AND (QuoteForBinary = TYPEY) AND
- (Def8QuoteMode <> TYPEY) THEN
- BEGIN
- BinaryMode := Quoted;
- QuoteForBinary := Def8QuoteMode;
- END;
-
- { Make sure that Quote Character is OK }
- IF (RunType = Transmit) AND (BinaryMode <> Quoted) THEN
- QuoteForBinary := ENDSTR;
- END;
-
- { Externals for RT-11 }
-
- PROCEDURE ICON; { set up console }
- EXTERNAL;
-
- PROCEDURE ITIME; { set up timer }
- EXTERNAL;
-
- PROCEDURE RCON; { Reset console }
- EXTERNAL;
-
- PROCEDURE RTIME; { Reset Timer }
- EXTERNAL;
-
- PROCEDURE Virtual; { Virtual terminal }
- EXTERNAL;
-
- PROCEDURE SetLine; { Set up DL11 line }
- EXTERNAL;
-
- PROCEDURE SYSinit; { special initialization }
- BEGIN
- END;
-
-
- PROCEDURE SYSfinish; { System dependent }
- BEGIN
- RTIME;
- RCON;
- END;
-
- PROCEDURE StartRun; { initialization as necessary }
- BEGIN
- State := Init; { send initiate is the start state }
- NumTry := 0; { say no tries yet }
- RunTime := 0;
-
- NumSendPacks := 0;
- NumRecvPacks := 0;
- NumACK := 0;
- NumNAK := 0;
- NumACKrecv := 0;
- NumNAKrecv := 0;
- NumBADrecv := 0;
- ChInFileSend := 0.0;
- ChInPackSend := 0.0;
- ChInFileRecv := 0.0;
- ChInFileRecv := 0.0;
-
- ITIME;
- ICON;
-
- END;
-
- PROCEDURE OpenPort;
- BEGIN
- IF InvalidConnection
- THEN
- BEGIN
- InvalidConnection := false;
- LineIn := DL11LINE;
- LineOut := DL11LINE;
- SetLine;
- END;
- END;
-
- PROCEDURE BadVTerminalConnect;
- BEGIN;
- writeln('Bad Terminal Connection');
- END;
-
-
- PROCEDURE MakeConnection;
- { connect to remote }
- BEGIN
- writeln('[Connecting to remote host, Type CTRL-]C to return]');
- Virtual;
- writeln('[Connection closed, back at RT-11]');
- END;
-
-
- PROCEDURE DebugPacket({ Using } mes : cstring;
- { Using } VAR p : Ppack);
- { Print Debugging Info }
- BEGIN
- PutCon(mes,STDERR);
- WITH p^ DO
- BEGIN
- PutNum(Unchar(count),STDERR);
- PutNum(Unchar(seq),STDERR);
- putcf(BLANK,STDERR);
- putcf(ptype,STDERR);
- putcf(NEWLINE,STDERR);
- putstr(data,STDERR);
- putcf(NEWLINE,STDERR);
- END;
- END;
-
-
- PROCEDURE ReSendPacket;
- { re -sends previous packet }
- BEGIN
- NumSendPacks := NumSendPacks+1;
- AddTo(ChInPackSend,Pad + UnChar(LastPacket^.count) + 3);
- IF Debug
- THEN DebugPacket('Re-Sending ... ',LastPacket);
- PutPacket(LastPacket);
- END;
-
-
-
- PROCEDURE SendPacket;
- { expects count as length of data portion }
- { and seq as number of packet }
- { builds & sends packet }
- VAR
- i,len,chksum : integer;
- temp : Ppack;
- BEGIN
- IF (NumTry <> 1) AND (RunType = Transmit )
- THEN
- ReSendPacket
- ELSE
- BEGIN
- WITH ThisPacket^ DO
- BEGIN
- mark :=SOH; { mark }
- len := count; { save length }
- count := MakeChar(len+3); { count = 3+length of data }
- seq := MakeChar(seq); { seq number }
- chksum := count + seq + ptype;
- IF ( len > 0)
- THEN { is there data ? }
- FOR i:= 1 TO len DO
- IF (data[i] >= 0)
- THEN
- chksum := chksum + data[i]
- ELSE
- chksum := chksum + data[i] + 256;
- { assume -128 .. 127 for characters }
- chksum := CheckFunction(chksum); { calculate checksum }
- data[len+1] := MakeChar(chksum); { make printable & output }
- IF OneWayOnly THEN
- BEGIN
- data[len+2] := CR; { Use CRLF }
- data[len+3] := NEWLINE;
- data[len+4] := ENDSTR;
- END
- ELSE
- BEGIN
- data[len+2] := SendEOL; { EOL }
- data[len+3] := ENDSTR;
- END;
- END;
-
-
- NumSendPacks := NumSendPacks+1;
- IF Debug
- THEN DebugPacket('Sending ... ',ThisPacket);
-
- PutPacket(ThisPacket);
-
- IF RunType = Transmit
- THEN
- BEGIN
- AddTo(ChInPackSend,Pad + len + 6);
- temp := LastPacket;
- LastPacket := ThisPacket;
- ThisPacket := temp;
- END;
- END
- END;
-
-
-
- PROCEDURE SendACK({ Using } n:integer); { send ACK packet }
- BEGIN
- WITH ThisPacket^ DO
- BEGIN
- count := 0;
- seq := n;
- ptype := TYPEY;
- END;
- SendPacket;
- NumACK := NumACK+1;
- END;
-
- PROCEDURE SendNAK({ Using } n:integer); { send NAK packet }
- BEGIN
- WITH ThisPacket^ DO
- BEGIN
- count := 0;
- seq := n;
- ptype := TYPEN;
- END;
- SendPacket;
- NumNAK := NumNAK+1;
- END;
-
- PROCEDURE ErrorPack({ Using } c:cstring);
- { output Error packet if necessary -- then exit }
- BEGIN
- IF Local
- THEN
- Putcln(c,STDERR);
-
- WITH ThisPacket^ DO
- BEGIN
- seq := n;
- ptype := TYPEE;
- CtoS(c,data);
- count := length(data);
- END;
-
- SendPacket;
- FinishUp(false);
- StipHalt;
- END;
-
-
-
- PROCEDURE Verbose({ Using } c:cstring);
- { Print message if verbosity }
- BEGIN
- IF Verbosity
- THEN
- Putcln(c,STDERR);
- END;
-
-
- PROCEDURE PutErr({ Using } c:cstring);
- { Print error_messages }
- BEGIN
- IF Local
- THEN
- Putcln(c,STDERR);
- END;
-
- {$E-}
- { Turn off Externals here }
-
- PROCEDURE Field1; { Count }
- VAR
- test: boolean;
- BEGIN
- WITH NextPacket^ DO
- BEGIN
- count := UnChar(t);
- test := (count >= 3) OR (count <= SizeRecv-2);
- InputPacket^.count := t;
- IF NOT test
- THEN
- Verbose('Bad count ');
- isgood := isgood AND test;
- END;
- END;
-
- PROCEDURE Field2; { Packet Number }
- VAR
- test : boolean;
- BEGIN
- WITH NextPacket^ DO
- BEGIN
- seq := UnChar(t);
- test := (seq >= 0) OR (seq <= 63);
- InputPacket^.seq := t;
- IF NOT test
- THEN
- Verbose('Bad seq number ');
- isgood := isgood AND test;
- END;
- END;
-
- PROCEDURE Field3; { Packet Type }
- VAR
- test : boolean;
- BEGIN
- WITH NextPacket^ DO
- BEGIN
- ptype := t;
- test := (t =TYPEB) OR (t=TYPED) OR (t=TYPEE) OR (t=TYPEF)
- OR (t=TYPEN) OR (t=TYPES) OR (t=TYPEY) OR (t=TYPEZ);
- InputPacket^.ptype := t;
- IF NOT test
- THEN
- Verbose('Bad Packet Type ');
- isgood := isgood AND test;
- END;
- END;
-
- PROCEDURE ProcessQuoted; { for Data }
- BEGIN
- WITH NextPacket^ DO
- BEGIN
- IF (t=MyQuote) OR (t=QuoteForBinary)
- THEN { character is quote }
- BEGIN
- IF control
- THEN { quote ,quote }
- BEGIN
- data[dataptr] := t + ishigh;
- dataptr := dataptr+1;
- control := false;
- ishigh := 0;
- END
- ELSE IF (t=MyQuote) THEN { set control on }
- control := true
- END
- ELSE { not quote }
- IF control
- THEN { convert to control }
- BEGIN
- data[dataptr] := ctl(t) + ishigh;
- dataptr := dataptr+1;
- control := false;
- ishigh := 0;
- END
- ELSE { regular data }
- BEGIN
- data[dataptr] := t + ishigh;
- dataptr := dataptr+1;
- ishigh := 0;
- END;
- END;
- END;
-
- PROCEDURE Field4; { Data }
- BEGIN
- PacketPtr := PacketPtr+1;
- InputPacket^.data[PacketPtr] := t;
- WITH NextPacket^ DO
- BEGIN
- IF ((ptype = TYPES) or (ptype = TYPEY))
- THEN
- BEGIN
- data[dataptr] := t;
- dataptr := dataptr+1;
- END
- ELSE
- BEGIN
- IF (BinaryMode = Quoted) THEN
- BEGIN { has it been quited ?}
- IF (NOT control) AND (t = QuoteForBinary)
- THEN ishigh := 128
- ELSE
- ProcessQuoted;
- END
- ELSE
- ProcessQuoted; { do regular quoting }
- END;
- END;
- END;
-
- PROCEDURE Field5; { Check Sum }
- VAR
- test : boolean;
- BEGIN
- WITH InputPacket^ DO
- BEGIN
- PacketPtr := PacketPtr +1;
- data[PacketPtr] := t;
- PacketPtr := PacketPtr +1;
- data[PacketPtr] := ENDSTR;
- END;
- { end of input string }
- check := CheckFunction(check);
- check := MakeChar(check);
- test := (t=check);
- isgood := isgood AND test;
- NextPacket^.data[dataptr] := ENDSTR;
- { end of data string }
- finished := true; { set finished }
- END;
-
- PROCEDURE BuildPacket;
- { receive packet & validate checksum }
- VAR
- temp : Ppack;
- BEGIN
- WITH NextPacket^ DO
- BEGIN
- IF restart
- THEN
- BEGIN
- { read until get SOH marker }
- IF (t = SOH)
- THEN
- BEGIN
- finished := false; { set varibles }
- control := false;
- ishigh := 0; { no shift }
- isgood := true;
- seq := -1; { set return values to bad packet }
- ptype := QUESTION;
- data[1] := ENDSTR;
- data[MAXSTR] := ENDSTR;
-
- restart := false;
- fld := 0;
- dataptr := 1;
- PacketPtr := 0;
- check := 0;
- END;
- END
- ELSE { have started packet }
- BEGIN
- IF (t=SOH) { check for restart or EOL }
- THEN
- restart := true
- ELSE
- IF (t=myEOL)
- THEN
- BEGIN
- finished := true;
- isgood := false;
- END
- ELSE
- BEGIN
- CASE fld OF
- { increment field number }
- 0: fld := 1;
- 1: fld := 2;
- 2: fld := 3;
- 3:
- IF (count=3) { no data }
- THEN
- fld := 5
- ELSE
- fld := 4;
- 4:
- IF (PacketPtr>=count-3) { end of data }
- THEN
- fld := 5;
- END { case };
-
- IF (fld<>5)
- THEN
- check := check+t; { add into checksum }
-
- CASE fld OF
- 1: Field1;
- 2: Field2;
- 3: Field3;
- 4: Field4;
- 5: Field5;
- END;
- { case }
- END;
- END;
-
- IF finished
- THEN
- BEGIN
- IF (ptype=TYPEE) AND isgood
- THEN { error_packets }
- BEGIN
- IF Local
- THEN
- putstr(data,STDERR);
- putcf(NEWLINE,STDERR);
- FinishUp(false);
- StipHalt;
- END;
-
- NumRecvPacks := NumRecvPacks+1;
- IF Debug
- THEN
- BEGIN
- DebugPacket('Received ... ',InputPacket);
- IF isgood
- THEN
- PutCln('Is Good ',STDERR);
- END;
-
- temp := CurrentPacket;
- CurrentPacket := NextPacket;
- NextPacket := temp;
- END;
- END;
- END;
-
- {$E+}
- { Turn on Externals here }
-
- FUNCTION RecvPacket: boolean;
- BEGIN
- StartTimer;
- finished := false;
- restart := true;
- FromConsole := nothing; { No Interupt }
- REPEAT
- t := GetIn;
- IF Local { check Interupt }
- THEN
- CASE FromConsole OF
- abortnow:
- BEGIN
- ErrorPack('Aborting Transfer ');
- END;
- nothing: { nothing };
- CRin:
- BEGIN
- t := MyEOL;
- FromConsole := nothing;
- END;
- END;
- { case }
- IF (t <> NULLCHAR)
- THEN
- BuildPacket;
- UNTIL finished OR (TimeLeft <= 0);
- IF (TimeLeft <= 0)
- THEN
- BEGIN
- CurrentPacket^.ptype := TYPET;
- restart := true;
- isgood := true;
- Verbose('Timed Out ')
- END;
- StopTimer;
- RecvPacket := isgood;
- END;
-
- FUNCTION RecvACK : { Returning } boolean;
- { receive ACK with correct number }
- VAR
- Ok: boolean;
- BEGIN
- IF (NOT OneWayOnly )
- THEN
- Ok := RecvPacket;
- WITH CurrentPacket^ DO
- BEGIN
- IF (ptype=TYPEY)
- THEN
- NumACKrecv := NumACKrecv+1
- ELSE
- IF (ptype=TYPEN)
- THEN
- NumNAKrecv := NumNAKrecv+1
- ELSE
- IF NOT OneWayOnly
- THEN
- NumBadrecv := NumBadrecv +1;
- { got right one ? }
- RecvACK := ( Ok AND (ptype=TYPEY) AND (n=seq))
- OR ( OneWayOnly)
- END;
- END;
-
-
-
-
-