home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
iclvme2900.tar.gz
/
iclvme2900.tar
/
kmt_pp_module
< prev
next >
Wrap
Text File
|
1987-07-14
|
68KB
|
1,790 lines
MODULE KMT_PP_MODULE;
@******************************************************************************@
@* *@
@* Mode definitions *@
@* *@
@******************************************************************************@
MODE
KMT_TRACE_FLAGS_S IS WORD STRUCT (
BIT PH_TRACING,
PP_TRACING,
FH_TRACING,
DH_TRACING,
28-BIT SPARE);
MODE
KMT_FH_RECORD_DETAILS_S IS STRUCT (
BOOL FILE_OPEN,
NEW_RECORD,
END_OF_FILE,
WORD TEXT_TYPE, @ 0 = EBCDIC @
@ 1 = ASCII @
@ 2 = BINARY @
INT MAX_RECORD_LENGTH,
RECORD_LENGTH,
(4098) BYTE RECORD); @ Maximum record size of 4096 @
@ plus 2 bytes for CRLF pair @
@ when constructing output @
@ records @
MODE
KMT_DH_DEVICE_DETAILS_S IS STRUCT (
BOOL FILE_OPEN,
WORD MAX_INPUT_LENGTH,
MAX_OUTPUT_LENGTH,
INPUT_PARITY,
OUTPUT_PARITY,
PAUSE);
MODE
KMT_PP_PACKET_DATA_S IS STRUCT (
INT DATA_LENGTH,
(91) BYTE DATA);
MODE
KMT_PP_CONFG_PARAMS_S IS STRUCT (
BYTE MARK,
MAXL,
TIME,
NPAD,
PADC,
EOL,
QCTL,
QBIN,
CHKT,
REPT,
4-BYTE CAPAS);
MODE
KMT_PP_PACKET_STATISTICS_S IS STRUCT (
INT INPUT_TOTAL,
OUTPUT_TOTAL);
MODE
KMT_MTM_VALUES IS ANY (
LONG WORD LW_VALUE,
LONG INT LI_VALUE,
REF WORD RW_VALUE,
REF INT RI_VALUE,
REF LONG WORD RLW_VALUE,
REF LONG INT RLI_VALUE,
REF () BYTE RVB_VALUE,
REF () REF () BYTE RVRVB_VALUE);
***PAGE
@******************************************************************************@
@* *@
@* External procedure references *@
@* *@
@******************************************************************************@
EXT
PROC
(REF () BYTE, @ OUTPUT_PACKET @
BOOL, @ PROMPT @
RESPONSE @ RESPONSE @
) KMT_DH_OUTPUT;
EXT
PROC
(REF () BYTE, @ INPUT_BUFFER @
REF INT, @ INPUT_BUFFER_LENGTH @
RESPONSE @ RESPONSE @
) KMT_DH_INPUT;
EXT
PROC
(INT, @ RESULT_CODE @
WORD, @ DESTINATION @
REF () KMT_MTM_VALUES, @ PARAMS @
LONG WORD, @ PE_CONTINGENCY_MESSAGE @
BOOL, @ DUMP @
BOOL @ UNRECOVERABLE @
) KMT_EH_LOG_ERROR;
EXT
PROC
(
RESPONSE @ RESPONSE @
) KMT_FH_READ;
EXT
PROC
(
RESPONSE @ RESPONSE @
) KMT_FH_WRITE;
EXT
PROC
(
WORD, @ CHAR @
WORD, @ I/O FLAG @
RESPONSE @ RESPONSE @
) KMT_SP_CHECK_VME_CHAR;
EXT
PROC
(
INT, @ TYPE @
REF () KMT_MTM_VALUES @ PARAMS @
) KMT_SP_LOG_TRACE_MESSAGE;
***PAGE
@******************************************************************************@
@* *@
@* External data references *@
@* *@
@******************************************************************************@
@ Constants: @
@ ********** @
EXT (256) BYTE
EBCDIC_TO_ASCII, @ translation tables @
ASCII_TO_EBCDIC;
EXT (26) INT
PACKET_CODES; @ packet codes to protocol handler state table events @
EXT INT
BAD_PKT,INVALID_PKT,UNS_PKT,NON_PKT;
***LINES(4)
@ Variables: @
@ ********** @
EXT (<CASCADE>)
REF KMT_TRACE_FLAGS_S KMT_TRACE_FLAGS;
EXT (<CASCADE>)
REF KMT_FH_RECORD_DETAILS_S KMT_FH_RECORD_DETAILS;
EXT (<CASCADE>)
REF KMT_DH_DEVICE_DETAILS_S KMT_DH_DEVICE_DETAILS;
EXT (<CASCADE>)
REF KMT_PP_CONFG_PARAMS_S KMT_PP_LOCAL_CONFG_PARAMS;
EXT (<CASCADE>)
REF KMT_PP_CONFG_PARAMS_S KMT_PP_REMOTE_CONFG_PARAMS;
EXT (<CASCADE>)
REF KMT_PP_PACKET_STATISTICS_S KMT_PP_PACKET_STATISTICS;
EXT (<CASCADE>)
REF REF () BYTE KMT_PH_INPUT_PACKET_DATA;
***LINES(4)
@ Results: @
@ ******** @
***LINES(4)
***PAGE
@******************************************************************************@
@* *@
@* Static data declarations. *@
@* *@
@******************************************************************************@
@ Constants: @
@ ********** @
STATIC WORD
EBCDIC IS 0, @ transfer codes @
ASCII IS 1,
BINARY IS 2;
STATIC INT
KMT_PP_PACKET_IN_MSG IS 251,
KMT_PP_PACKET_OUT_MSG IS 252,
KMT_PP_PACKET_DATA_IN_MSG IS 253,
KMT_PP_PACKET_DATA_OUT_MSG IS 254,
KMT_PP_PARAM_OUT_MSG IS 258,
KMT_PP_PARAM_IN_MSG IS 259;
***LINES(4)
@ Variables: @
@ ********** @
STATIC
KMT_PP_PACKET_DATA_S KMT_PP_INPUT_PACKET_DATA;
STATIC
KMT_PP_PACKET_DATA_S KMT_PP_OUTPUT_PACKET_DATA;
STATIC
REF () BYTE KMT_PP_RECALL_DATA;
***LINES(4)
@ Results: @
@ ******** @
***LINES(4)
***PAGE
@******************************************************************************@
@* *@
@* Procedure declarations *@
@* *@
@******************************************************************************@
STATIC
PROC
KMT_PP_CHECK_COMPLETE IS (
INT DATA_LENGTH,
REF REF () BYTE BUFFER) BOOL:
@******************************************************************************@
@* *@
@* This procedure is used to update a buffer pointer and to check if the *@
@* processing of BUFFER is complete. *@
@* The procedure returns TRUE if the processing of BUFFER has been completed, *@
@* FALSE otherwise. *@
@* *@
@******************************************************************************@
BEGIN
IF
LENGTH BUFFER GT DATA_LENGTH
THEN @ Incomplete, update pointer @
BUFFER := BUFFER(DATA_LENGTH::);
FALSE
ELSE @ Complete return ZLR @
BUFFER := BUFFER(SIZE 0);
TRUE
FI
END; @ KMT_PP_CHECK_COMPLETE @
***PAGE
STATIC
PROC
KMT_PP_MOVE IS (
() BYTE SOURCE,
REF REF () BYTE DESTINATION,
REF BOOL COMPLETE) INT:
@******************************************************************************@
@* *@
@* This procedure is used to move the source string into the destination *@
@* buffer and to check if the destination buffer is full. *@
@* The procedure returns the number of characters moved. *@
@* *@
@******************************************************************************@
BEGIN
INT S_LEN IS LENGTH SOURCE,
D_LEN IS LENGTH DESTINATION;
IF
S_LEN GT D_LEN
THEN @ Insufficient space in @
@ buffer for string @
UNLESS
COMPLETE IS NIL
THEN
COMPLETE := TRUE;
FI;
0
ELSE
DESTINATION(SIZE S_LEN) := SOURCE;
UNLESS
COMPLETE IS NIL
THEN
COMPLETE := KMT_PP_CHECK_COMPLETE (S_LEN,
DESTINATION);
FI;
S_LEN
FI
END; @ KMT_PP_MOVE @
***PAGE
STATIC
PROC
KMT_PP_GENERATE_CHECKSUM IS (
REF () BYTE PACKET) BYTE:
@******************************************************************************@
@* *@
@* This procedure is used to generate a checksum for the data contained in *@
@* the packet. *@
@* *@
@******************************************************************************@
BEGIN
WORD SUM := 0;
FOR I
FROM 1 @ 'MARK' character not @
@ included in checksum @
TO PACKET(1) - X"20"
DO
SUM := SUM + PACKET(I)
REPEAT;
((SUM + ((SUM & X'C0') SCALE -6)) & X'3F') + X"20"
END; @ KMT_PP_GENERATE_CHECKSUM @
***PAGE
STATIC
PROC
KMT_PP_LOG_TRACE_MESSAGE IS (
INT TYPE,
REF () BYTE PACKET):
@******************************************************************************@
@* *@
@* This procedure is used to log the packet contents to the job journal. *@
@* *@
@******************************************************************************@
BEGIN
INT PACKET_LENGTH IS LENGTH PACKET;
INT LEN := PACKET(1) - X"20",
SEQ := PACKET(2) - X"20",
TYP := PACKET_CODES(PACKET(3) - X"41");
() KMT_MTM_VALUES PARAMS := (PACKET @ COMPLETE PACKET @
AS KMT_MTM_VALUES.RVB_VALUE,
PACKET(0) @ MARK @
AS KMT_MTM_VALUES.RVB_VALUE,
LEN @ LEN @
AS KMT_MTM_VALUES.RI_VALUE,
SEQ @ SEQ @
AS KMT_MTM_VALUES.RI_VALUE,
TYP @ TYPE @
AS KMT_MTM_VALUES.RI_VALUE,
PACKET(4 SIZE PACKET_LENGTH - 5)
@ DATA @
AS KMT_MTM_VALUES.RVB_VALUE,
PACKET(PACKET_LENGTH - 1)
@ CHECKSUM @
AS KMT_MTM_VALUES.RVB_VALUE);
KMT_SP_LOG_TRACE_MESSAGE (TYPE,
PARAMS)
END; @ KMT_PP_LOG_TRACE_MESSAGE @
***PAGE
STATIC
PROC
KMT_PP_DATA_TRACE_MESSAGE IS (
INT TYPE,
INT CODE,
REF () BYTE DATA):
@******************************************************************************@
@* *@
@* This procedure is used to log the packet data to the job journal. *@
@* *@
@******************************************************************************@
BEGIN
INT CHAR_CODE := CODE;
() KMT_MTM_VALUES PARAMS := (CHAR_CODE @ character code of data @
AS KMT_MTM_VALUES.RI_VALUE,
DATA @ data @
AS KMT_MTM_VALUES.RVB_VALUE);
KMT_SP_LOG_TRACE_MESSAGE (TYPE,
PARAMS)
END; @ KMT_PP_DATA_TRACE_MESSAGE @
***PAGE
STATIC
PROC
KMT_PP_BUILD_PACKET_DATA IS (
REF REF () BYTE BUFFER,
REF REF () BYTE DATA,
WORD TEXT_TYPE,
REF BOOL BUFFER_COMPLETE) BOOL:
@******************************************************************************@
@* *@
@* This procedure is used to perform data translation of the data area *@
@* referenced by BUFFER. *@
@* If a binary file transfer is requested then the translation process *@
@* involves control character quoting and 8th bit prefixing. Otherwise (for *@
@* text files) the translation process involves control character quoting and *@
@* EBCDIC to ASCII data translation. *@
@* If the whole of BUFFER has been translated then BUFFER_COMPLETE is set *@
@* TRUE and BUFFER is returned referencing a zero length record. Otherwise *@
@* BUFFER_COMPLETE is returned FALSE and BUFFER is returned referencing the *@
@* untranslated part of the original buffer. *@
@* The translated data is returned in the area referenced by DATA. *@
@* The procedure returns TRUE if there is insufficient space in DATA for more *@
@* of the translated data. *@
@* *@
@******************************************************************************@
BEGIN
STATIC BYTE
SPACE IS X"20", @ ASCII codes @
DEL IS X"7F";
BYTE
QCTL IS KMT_PP_LOCAL_CONFG_PARAMS.QCTL,
QBIN IS KMT_PP_LOCAL_CONFG_PARAMS.QBIN;
() BYTE
QLF IS (QCTL,X"4A"), @ ASCII quoted LF @
QFF IS (QCTL,X"4C"), @ ASCII quoted FF @
QCR IS (QCTL,X"4D"), @ ASCII quoted CR @
QCRLF IS (QCTL,X"4D",QCTL,X"4A"); @ ASCII quoted CRLF @
BOOL
DATA_COMPLETE := FALSE;
SIM PROC PACKETISE IS (() BYTE SOURCE,INT DATA_LENGTH):
BEGIN
IF KMT_PP_MOVE(SOURCE,DATA,DATA_COMPLETE) NE 0
THEN BUFFER_COMPLETE := KMT_PP_CHECK_COMPLETE(DATA_LENGTH,BUFFER)
FI
END @ PACKETISE @ ;
BUFFER_COMPLETE := (LENGTH BUFFER LE 0);
UNTIL DATA_COMPLETE OR BUFFER_COMPLETE
DO
IF TEXT_TYPE GT EBCDIC
THEN @ ASCII or binary data @
INT SEQ_LEN := 0;
(3) BYTE SEQ;
BYTE THIS_CHAR := BUFFER(0);
SIM PROC ADD_TO_SEQ IS (BYTE OCTET):
BEGIN
SEQ(SEQ_LEN) := OCTET;
SEQ_LEN := SEQ_LEN+1
END @ ADD_TO_SEQ @ ;
IF (THIS_CHAR GT DEL) AND (TEXT_TYPE EQ BINARY)
THEN @ need to add 8th bit prefix @
ADD_TO_SEQ(QBIN)
FI;
THIS_CHAR := THIS_CHAR & X"7F";
IF (THIS_CHAR LT SPACE) OR (THIS_CHAR EQ DEL)
THEN @ control character @
ADD_TO_SEQ(QCTL);
THIS_CHAR := THIS_CHAR NEQ X"40"
ELSF (THIS_CHAR EQ QCTL) OR (THIS_CHAR EQ QBIN AND TEXT_TYPE EQ BINARY)
THEN @ special char, quote it @
ADD_TO_SEQ(QCTL)
FI;
ADD_TO_SEQ(THIS_CHAR);
PACKETISE(SEQ(SIZE SEQ_LEN),1)
ELSE @ EBCDIC data @
BYTE THIS_CHAR IS EBCDIC_TO_ASCII(BUFFER(0));
IF THIS_CHAR GT DEL
THEN @ Format effector @
IF (LENGTH BUFFER LT 2) OR (THIS_CHAR EQ X"FB")
THEN @ Newline FE (1 byte) or FE at end of record with no specifier@
IF THIS_CHAR EQ X"FB"
THEN @ End of record so ignore @
BUFFER_COMPLETE := KMT_PP_CHECK_COMPLETE(1,BUFFER)
ELSE @ Newline @
PACKETISE(QCRLF,1)
FI
ELSE @ FE with qualifier @
REF BYTE QUALIFIER IS BUFFER(1);
SIM PROC EXPAND_FE IS (() BYTE EXPANSION):
BEGIN
IF
QUALIFIER :=
QUALIFIER - W'(TO QUALIFIER - 1
UNTIL DATA_COMPLETE
DO
KMT_PP_MOVE(EXPANSION,DATA,
DATA_COMPLETE)
REPEAT);
QUALIFIER EQ 0
THEN
BUFFER_COMPLETE := KMT_PP_CHECK_COMPLETE(2,BUFFER)
FI
END @ EXPAND_FE @ ;
CASE X"FF" - THIS_CHAR
THEN @ multiple space @
EXPAND_FE(SPACE)
ELSE @ multiple newline @
IF QUALIFIER EQ X"00"
THEN @ translate to CR @
PACKETISE(QCR,2)
ELSE @ expand to CRLF pairs @
EXPAND_FE(QCRLF)
FI
ELSE @ vertical position @
IF (QUALIFIER EQ X"00")
THEN
PACKETISE(QFF,2)
ELSE
PACKETISE(QCRLF,2)
FI
ELSE @ horizontal position @
PACKETISE(SPACE,2)
ESAC
FI
ELSF THIS_CHAR EQ QCTL
THEN @ quote character @
PACKETISE((QCTL,THIS_CHAR),1)
ELSF (THIS_CHAR LT SPACE) OR (THIS_CHAR EQ DEL)
THEN @ control character @
PACKETISE((QCTL,THIS_CHAR NEQ X"40"),1)
ELSE @ printable character @
PACKETISE(THIS_CHAR,1)
FI
FI
REPEAT;
DATA_COMPLETE
END @ KMT_PP_BUILD_PACKET_DATA @ ;
***PAGE
STATIC
PROC
KMT_PP_UNQUOTE_CHAR IS (
REF () BYTE DATA,
REF BYTE UNQUOTED_CHAR,
REF INT SEQUENCE_LENGTH):
@******************************************************************************@
@* *@
@* This procedure is used to process a quoted (binary and/or control) *@
@* character sequence. *@
@* The area referenced by DATA contains the character sequence to be *@
@* processed. The area referenced by UNQUOTED_CHAR is returned containing the *@
@* unquoted character (with the control and 8th bit set as appropriate) and *@
@* the area referenced by SEQUENCE_LENGTH is returned containing the length *@
@* of the quoted sequence. If the first character in DATA is not a binary or *@
@* control quote character then UNQUOTED_CHAR is returned containing the *@
@* character and SEQUENCE_LENGTH is returned containing 1. *@
@* *@
@******************************************************************************@
BEGIN
WORD TEXT_TYPE IS KMT_FH_RECORD_DETAILS.TEXT_TYPE;
BYTE QCTL IS KMT_PP_REMOTE_CONFG_PARAMS.QCTL,
QBIN IS KMT_PP_REMOTE_CONFG_PARAMS.QBIN;
BYTE THIS_CHAR := DATA(0);
BYTE OR_MASK IS IF
(TEXT_TYPE EQ BINARY) AND (THIS_CHAR EQ QBIN)
THEN @ Binary file and 8th bit @
@ quoted character found @
THIS_CHAR := DATA(1);
SEQUENCE_LENGTH := 2;
X"80"
ELSE @ Not an 8th bit quoted @
@ character @
SEQUENCE_LENGTH := 1;
X"00"
FI;
IF
THIS_CHAR EQ QCTL
THEN @ Control quoted character @
THIS_CHAR := DATA(SEQUENCE_LENGTH);
SEQUENCE_LENGTH := SEQUENCE_LENGTH + 1;
IF
(THIS_CHAR NE QCTL) AND (THIS_CHAR NE QBIN OR TEXT_TYPE NE BINARY)
THEN @ Control character @
THIS_CHAR := THIS_CHAR NEQ X"40"
FI
FI;
UNQUOTED_CHAR := THIS_CHAR ! OR_MASK
END; @ KMT_PP_UNQUOTE_CHAR @
***PAGE
GLOBAL
STATIC (<STATUS 5>)
PROC
KMT_PP_TRANSLATE_TO_EBCDIC IS ():
@******************************************************************************@
@* *@
@* This procedure is used to translate the packet data from ASCII to EBCDIC *@
@* and to process any quoted characters. *@
@* The untranslated data is read from, and the translated data is returned in *@
@* the area referenced by KMT_PH_INPUT_PACKET_DATA. *@
@* *@
@******************************************************************************@
BEGIN
() BYTE UNTRANSLATED_DATA := KMT_PH_INPUT_PACKET_DATA;
@ Copy untranslated data @
REF () BYTE DATA := UNTRANSLATED_DATA;
BOOL DATA_COMPLETE := (LENGTH DATA LE 0);
INT T_LEN IS FOR I
UNTIL
DATA_COMPLETE
DO
INT SEQUENCE_LENGTH;
KMT_PP_UNQUOTE_CHAR (DATA,
KMT_PH_INPUT_PACKET_DATA(I),
SEQUENCE_LENGTH);
DATA_COMPLETE := KMT_PP_CHECK_COMPLETE (SEQUENCE_LENGTH,
DATA)
REPEAT;
KMT_PH_INPUT_PACKET_DATA := KMT_PH_INPUT_PACKET_DATA(SIZE T_LEN);
TRANSLATE (ASCII_TO_EBCDIC,
KMT_PH_INPUT_PACKET_DATA,
0,
NIL);
IF KMT_TRACE_FLAGS.PP_TRACING AND LENGTH KMT_PH_INPUT_PACKET_DATA > 0
THEN (<RARELY>)
(
KMT_PP_DATA_TRACE_MESSAGE(KMT_PP_PACKET_DATA_IN_MSG,
EBCDIC,
KMT_PH_INPUT_PACKET_DATA)
)
FI
END; @ KMT_PP_TRANSLATE_TO_EBCDIC @
***PAGE
GLOBAL
STATIC (<STATUS 5>)
PROC
KMT_PP_GET_PACKET IS (
REF INT TYPE,
REF INT SEQ,
RESPONSE RESULT):
@******************************************************************************@
@* *@
@* This procedure is used to receive a KERMIT packet from the remote end. *@
@* If a failure is detected whilst attempting to read a packet then TYPE is *@
@* set to BAD_PKT and the failing resultcode is returned. *@
@* If a zero length packet is read or no 'MARK' character is found in the *@
@* packet then TYPE is set to BAD_PKT and resultcode KMT_PP_NO_INPUT_DATA is *@
@* returned. *@
@* If the checksum validation fails then TYPE is set to BAD_PKT and *@
@* resultcode KMT_PP_INVALID_CHECKSUM is returned. *@
@* In all other cases TYPE will be set to either INVALID_PKT or the packet *@
@* type. In the case of an invalid packet then a resultcode of either UNS_PKT *@
@* or NON_PKT will be returned. *@
@* The packet sequence number is returned in the area referenced by SEQ and *@
@* the packet data is returned in the area referenced by *@
@* KMT_PH_INPUT_PACKET_DATA. *@
@* *@
@******************************************************************************@
BEGIN
INT KMT_PP_PACKET_IN_MSG IS 251,
KMT_PP_NO_INPUT_PACKET IS -80250,
KMT_PP_INVALID_CHECKSUM IS -80253,
KMT_PP_INVALID_PACKET_LENGTH IS -80254;
INT INPUT_PACKET_LENGTH,
INPUT_BUFFER_LENGTH,
PACKET_POINTER_LENGTH;
INT MAX_INPUT_LENGTH IS KMT_DH_DEVICE_DETAILS.MAX_INPUT_LENGTH;
REF () BYTE INPUT_PACKET,
PACKET_POINTER;
(MAX_INPUT_LENGTH) BYTE INPUT_BUFFER; @ Allows for padding and @
@ 'noise' characters @
IF
(
KMT_DH_INPUT (INPUT_BUFFER,
INPUT_BUFFER_LENGTH,
RESULT);
RESULT GT 0
)
THEN @ I/O error @
TYPE := BAD_PKT
ELSF
INPUT_BUFFER_LENGTH EQ 0
OR
(
BYTE MARK IS KMT_PP_REMOTE_CONFG_PARAMS.MARK;
REF () BYTE REM := INPUT_BUFFER(SIZE INPUT_BUFFER_LENGTH);
PACKET_POINTER := REM(SIZE 0);
UNTIL @ Skip all but last 'MARK' @
SCANUNQ (MARK, @ character @
REM,
0,
REM)
DO
PACKET_POINTER := REM;
REM := REM(1::)
REPEAT;
PACKET_POINTER_LENGTH := LENGTH PACKET_POINTER;
PACKET_POINTER_LENGTH LT 2
)
OR
(
INPUT_PACKET_LENGTH := PACKET_POINTER(1) - X"20" + 2;
PACKET_POINTER_LENGTH LT INPUT_PACKET_LENGTH
)
THEN @ Either 'MARK' character not @
@ found or insufficient data @
@ after 'MARK' character or a @
@ recoverable I/O error @
@ occurred. @
TYPE := BAD_PKT;
RESULT := KMT_PP_NO_INPUT_PACKET
ELSF
(
(INPUT_PACKET_LENGTH LT 5) OR (INPUT_PACKET_LENGTH GT 96)
)
THEN @ Packet length invalid @
TYPE := BAD_PKT;
RESULT := KMT_PP_INVALID_PACKET_LENGTH
ELSF
(
INPUT_PACKET := PACKET_POINTER(SIZE INPUT_PACKET_LENGTH);
IF
KMT_TRACE_FLAGS.PP_TRACING
THEN (<RARELY>)
(
KMT_PP_LOG_TRACE_MESSAGE (KMT_PP_PACKET_IN_MSG,
INPUT_PACKET)
)
FI;
INPUT_PACKET(INPUT_PACKET_LENGTH - 1) NE KMT_PP_GENERATE_CHECKSUM (
INPUT_PACKET)
)
THEN @ Checksum error @
TYPE := BAD_PKT;
RESULT := KMT_PP_INVALID_CHECKSUM
ELSE @ Validate packet type @
WORD PACKET_TYPE IS INPUT_PACKET(3) - X"41";
IF
PACKET_TYPE GT 25
THEN @ Not in range A to Z @
TYPE := INVALID_PKT;
RESULT := NON_PKT
ELSF
(
TYPE := PACKET_CODES(PACKET_TYPE);
TYPE LT 0
)
THEN
RESULT := TYPE;
TYPE := INVALID_PKT
ELSE
REF INT DATA_LENGTH IS KMT_PP_INPUT_PACKET_DATA.DATA_LENGTH;
REF () BYTE DATA IS KMT_PP_INPUT_PACKET_DATA.DATA;
REF INT STATISTICS IS
KMT_PP_PACKET_STATISTICS.INPUT_TOTAL;
STATISTICS := STATISTICS + 1;
SEQ := INPUT_PACKET(2) - X"20";
DATA_LENGTH := INPUT_PACKET_LENGTH - 5;
MOVE (INPUT_PACKET(4 SIZE DATA_LENGTH),
DATA,
0,
X"00",
NIL,
NIL);
KMT_PH_INPUT_PACKET_DATA := DATA(SIZE DATA_LENGTH)
FI
FI
END; @ KMT_PP_GET_PACKET @
***PAGE
GLOBAL
STATIC (<STATUS 5>)
PROC
KMT_PP_SEND_PACKET IS (
INT TYPE,
INT SEQ,
BOOL PROMPT,
RESPONSE RESULT):
@******************************************************************************@
@* *@
@* This procedure is used to frame and send a KERMIT packet to the remote end.*@
@* TYPE and SEQ specify the packet type and sequence number respectively. *@
@* The packet data and length is read from the areas *@
@* KMT_PP_OUTPUT_PACKET_DATA.DATA and KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH *@
@* respectively. *@
@* If PROMPT is set TRUE then read interest is set at the PFI for the next *@
@* input packet. *@
@* *@
@******************************************************************************@
BEGIN
INT KMT_PP_PACKET_OUT_MSG IS 252;
INT DATA_LENGTH IS KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH;
REF () BYTE DATA IS KMT_PP_OUTPUT_PACKET_DATA.DATA;
INT OUTPUT_PACKET_LENGTH IS 5 + DATA_LENGTH;
(OUTPUT_PACKET_LENGTH) BYTE OUTPUT_PACKET;
STATIC () BYTE PACKET_TYPES IS X"00" @ Not used @
X"42" @ B packet @
X"44" @ D packet @
X"45" @ E packet @
X"46" @ F packet @
X"47" @ G packet @
X"49" @ I packet @
X"4B" @ K packet @
X"4E" @ N packet @
X"52" @ R packet @
X"53" @ S packet @
X"59" @ Y packet @
X"5A"; @ Z packet @
OUTPUT_PACKET(0) := KMT_PP_LOCAL_CONFG_PARAMS.MARK;
OUTPUT_PACKET(1) := DATA_LENGTH + 3 + X"20";
OUTPUT_PACKET(2) := SEQ + X"20";
OUTPUT_PACKET(3) := PACKET_TYPES(TYPE);
OUTPUT_PACKET(4 SIZE DATA_LENGTH) := DATA;
OUTPUT_PACKET(OUTPUT_PACKET_LENGTH - 1) := KMT_PP_GENERATE_CHECKSUM (
OUTPUT_PACKET);
IF
KMT_TRACE_FLAGS.PP_TRACING
THEN (<RARELY>)
(
KMT_PP_LOG_TRACE_MESSAGE (KMT_PP_PACKET_OUT_MSG,
OUTPUT_PACKET)
)
FI;
KMT_DH_OUTPUT (OUTPUT_PACKET,
PROMPT,
RESULT);
IF
RESULT LE 0
THEN
REF INT STATISTICS IS
KMT_PP_PACKET_STATISTICS.OUTPUT_TOTAL;
STATISTICS := STATISTICS + 1
FI
END; @ KMT_PP_SEND_PACKET @
***PAGE
GLOBAL
STATIC (<STATUS 5>)
PROC
KMT_PP_BUILD_FILE_PACKET_DATA IS (
RESPONSE RESULT):
@******************************************************************************@
@* *@
@* This procedure is used to read file records and to construct data packets *@
@* from the record performing data translation, binary and control character *@
@* character quoting as appropriate. *@
@* The record and length are returned in the data areas *@
@* KMT_FH_RECORD_DETAILS.RECORD and KMT_FH_RECORD_DETAILS.RECORD_LENGTH *@
@* respectively. The processed packet data and length are returned is the *@
@* data areas *@
@* KMT_PP_OUTPUT_PACKET_DATA.DATA and KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH *@
@* respectively. *@
@* End of file is indicated by returning resultcode DML_READ_PSEUDO_NODE. *@
@* *@
@******************************************************************************@
BEGIN
INT DML_READ_PSEUDO_NODE IS 9034;
REF BOOL END_OF_FILE IS KMT_FH_RECORD_DETAILS.END_OF_FILE;
REF INT DATA_LENGTH IS KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH;
RESULT := 0;
IF
END_OF_FILE
THEN @ End of file reached during @
@ previous read @
DATA_LENGTH := 0;
RESULT := DML_READ_PSEUDO_NODE
ELSF
(
REF BOOL NEW_RECORD IS KMT_FH_RECORD_DETAILS.NEW_RECORD;
WORD TEXT_TYPE IS KMT_FH_RECORD_DETAILS.TEXT_TYPE;
REF INT RECORD_LENGTH IS KMT_FH_RECORD_DETAILS.RECORD_LENGTH;
REF () BYTE RECORD IS KMT_FH_RECORD_DETAILS.RECORD;
BYTE QCTL IS KMT_PP_LOCAL_CONFG_PARAMS.QCTL;
BYTE MAXL IS KMT_PP_REMOTE_CONFG_PARAMS.MAXL;
REF () BYTE DATA IS KMT_PP_OUTPUT_PACKET_DATA.DATA(SIZE MAXL - 5);
() BYTE QCRQLF IS (QCTL, X"4D", QCTL, X"4A");
@ Quoted CRLF @
INT D_LEN IS LENGTH DATA;
REF () BYTE DATA_REM := DATA;
(91) BYTE PP_TRACE_BUFFER; @ debug trace area @
REF () BYTE PP_TRACE_PTR := PP_TRACE_BUFFER;
INT PP_TRACE_COUNT := 0;
UNTIL
(
BOOL DATA_COMPLETE;
IF
NEW_RECORD
AND
(
KMT_FH_READ (RESULT);
IF
RESULT LE 0
THEN @ Record read successfully @
KMT_PP_RECALL_DATA := RECORD(SIZE RECORD_LENGTH);
FI;
RESULT GT 0
)
THEN @ Read error or end of file @
END_OF_FILE := TRUE;
DATA_COMPLETE := TRUE
ELSE @ Build packet data from @
@ record @
REF () BYTE TRACE_PTR := KMT_PP_RECALL_DATA;
INT TRACE_CT;
DATA_COMPLETE := KMT_PP_BUILD_PACKET_DATA (KMT_PP_RECALL_DATA,
DATA_REM,
TEXT_TYPE,
NEW_RECORD);
@ copy source to trace buffer @
TRACE_CT := LENGTH TRACE_PTR - LENGTH KMT_PP_RECALL_DATA;
PP_TRACE_PTR(SIZE TRACE_CT) := TRACE_PTR(SIZE TRACE_CT);
PP_TRACE_COUNT := PP_TRACE_COUNT + TRACE_CT;
PP_TRACE_PTR := PP_TRACE_BUFFER(PP_TRACE_COUNT::);
IF
TEXT_TYPE EQ BINARY
THEN @ Binary file transfer don't @
@ add CRLF end of record @
@ marker @
SKIP
ELSF
NEW_RECORD
THEN @ EBCDIC or ASCII file @
@ transfer and end of record. @
@ Move in quote CRLF, end of @
@ record marker @
NEW_RECORD := KMT_PP_MOVE (QCRQLF,
DATA_REM,
DATA_COMPLETE) NE 0;
IF NEW_RECORD @ add new record mark to trace @
THEN
PP_TRACE_PTR(SIZE 4) := IF TEXT_TYPE = EBCDIC
THEN " // "
ELSE X"202F2F20"
FI;
PP_TRACE_COUNT := PP_TRACE_COUNT + 4;
PP_TRACE_PTR := PP_TRACE_BUFFER(PP_TRACE_COUNT::);
FI
FI
FI;
DATA_COMPLETE
)
DO
SKIP
REPEAT;
DATA_LENGTH := D_LEN - LENGTH DATA_REM;
IF KMT_TRACE_FLAGS.PP_TRACING AND PP_TRACE_COUNT > 0
THEN (<RARELY>)
(
IF TEXT_TYPE = ASCII
THEN
TRANSLATE(ASCII_TO_EBCDIC,
PP_TRACE_BUFFER(SIZE PP_TRACE_COUNT),
0,
NIL)
FI;
KMT_PP_DATA_TRACE_MESSAGE(KMT_PP_PACKET_DATA_OUT_MSG,
TEXT_TYPE,
PP_TRACE_BUFFER(SIZE PP_TRACE_COUNT))
)
FI;
(RESULT EQ DML_READ_PSEUDO_NODE) AND (DATA_LENGTH NE 0)
)
THEN @ End of file reached but @
@ packet data remains. @
@ Return end of file on next @
@ call @
RESULT := 0
FI
END; @ KMT_PP_BUILD_FILE_PACKET_DATA @
***PAGE
GLOBAL
STATIC (<STATUS 5>)
PROC
KMT_PP_BUILD_STRING_PACKET_DATA IS (
REF () BYTE STRING,
RESPONSE RESULT):
@******************************************************************************@
@* *@
@* This procedure is used to translate the data held in STRING from EBCDIC to *@
@* ASCII. *@
@* The translated data and length is returned in the area *@
@* KMT_PP_OUTPUT_PACKET_DATA.DATA and KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH *@
@* respectively. *@
@* If the translated data length exceeds the maximum packet data length then *@
@* resultcode KMT_PP_STRING_TOO_BIG is returned. *@
@* *@
@******************************************************************************@
BEGIN
INT KMT_PP_STRING_TOO_BIG IS 80256;
INT MAXL IS KMT_PP_REMOTE_CONFG_PARAMS.MAXL;
REF INT DATA_LENGTH IS KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH;
REF () BYTE DATA IS KMT_PP_OUTPUT_PACKET_DATA.DATA(SIZE MAXL - 5);
INT STRING_LENGTH IS IF
STRING IS NIL
THEN
0
ELSE
LENGTH STRING
FI;
IF
STRING_LENGTH EQ 0
THEN @ NIL or ZLR supplied @
DATA_LENGTH := 0;
RESULT := 0
ELSE
() BYTE STRING_COPY := STRING; @ Don't want to corrupt @
@ original string @
REF () BYTE STRING_POINTER := STRING_COPY,
DATA_REM := DATA;
RESULT := IF
(
BOOL STRING_COMPLETE := TRUE;
KMT_PP_BUILD_PACKET_DATA (STRING_POINTER,
DATA_REM,
EBCDIC,
STRING_COMPLETE);
STRING_COMPLETE
)
THEN
0
ELSE @ String too big @
KMT_PP_STRING_TOO_BIG
FI;
DATA_LENGTH := LENGTH DATA - LENGTH DATA_REM;
IF KMT_TRACE_FLAGS.PP_TRACING
THEN (<RARELY>)
(
KMT_PP_DATA_TRACE_MESSAGE(KMT_PP_PACKET_DATA_OUT_MSG,EBCDIC,
STRING(SIZE (STRING_LENGTH - LENGTH STRING_POINTER)))
)
FI
FI;
END; @ KMT_PP_BUILD_STRING_PACKET_DATA @
***PAGE
GLOBAL
STATIC (<STATUS 5>)
PROC
KMT_PP_BUILD_FILE_RECORD IS (
RESPONSE RESULT):
@******************************************************************************@
@* *@
@* This procedure is used to construct file records from KERMIT data packets *@
@* received. For text files control character quoting and data translation *@
@* from ASCII to EBCDIC is performed. For binary files control character *@
@* quoting and 8th bit quoting is performed. *@
@* The packet data is read from the area referenced by *@
@* KMT_PH_INPUT_PACKET_DATA. The processed record and length is returned in *@
@* the areas KMT_FH_RECORD_DETAILS.RECORD and *@
@* KMT_FH_RECORD_DETAILS.RECORD.LENGTH respectively. *@
@* When the end of record is detected the record is written to the file. *@
@* *@
@******************************************************************************@
BEGIN
INT KMT_PP_RECORD_TOO_BIG IS 80255;
REF () BYTE DATA := KMT_PH_INPUT_PACKET_DATA;
INT DATA_LENGTH IS LENGTH DATA;
REF BOOL NEW_RECORD IS KMT_FH_RECORD_DETAILS.NEW_RECORD;
WORD TEXT_TYPE IS KMT_FH_RECORD_DETAILS.TEXT_TYPE;
INT MAX_RECORD_LENGTH := KMT_FH_RECORD_DETAILS.MAX_RECORD_LENGTH;
REF INT RECORD_LENGTH IS KMT_FH_RECORD_DETAILS.RECORD_LENGTH;
INT RECORD_SIZE IS IF
TEXT_TYPE EQ BINARY
THEN @ Binary file transfer. CRLF @
@ end of record terminator @
@ not required @
MAX_RECORD_LENGTH
ELSE @ EBCDIC or ASCII file xfer. @
@ Allow for CRLF pair, end of @
@ record terminator @
MAX_RECORD_LENGTH + 2
FI;
REF () BYTE RECORD IS KMT_FH_RECORD_DETAILS.RECORD(SIZE RECORD_SIZE);
() BYTE LF IS X"0A", @ ASCII LF @
CR IS X"0D"; @ CR @
() BYTE CRLF IS (CR,LF);
BOOL DATA_COMPLETE := (DATA_LENGTH LE 0);
(96) BYTE PP_TRACE_BUFFER; @ packet trace variables @
REF () BYTE PP_TRACE_PTR := PP_TRACE_BUFFER,
TRACE_PTR := KMT_PP_RECALL_DATA;
INT PP_TRACE_COUNT := 0;
RESULT := 0;
UNTIL
DATA_COMPLETE OR (RESULT GT 0)
DO
INT LAST_CHAR_INDEX IS IF
NEW_RECORD
THEN
KMT_PP_RECALL_DATA := RECORD;
TRACE_PTR := RECORD; @ (for trace) @
-1
ELSE
RECORD_SIZE - (LENGTH KMT_PP_RECALL_DATA + 1)
FI;
BYTE UNQUOTED_CHAR;
INT SEQUENCE_LENGTH;
KMT_PP_UNQUOTE_CHAR (DATA,
UNQUOTED_CHAR,
SEQUENCE_LENGTH);
IF
KMT_PP_MOVE (UNQUOTED_CHAR,
KMT_PP_RECALL_DATA,
NEW_RECORD) NE 0
THEN @ Moved in data @
DATA_COMPLETE := KMT_PP_CHECK_COMPLETE (SEQUENCE_LENGTH,
DATA);
FI;
IF
TEXT_TYPE EQ BINARY
THEN @ Binary file transfer @
RECORD_LENGTH := RECORD_SIZE - LENGTH KMT_PP_RECALL_DATA;
IF
NEW_RECORD
THEN @ Record complete, output it @
@ (obtain trace info) @
INT TRACE_CT := LENGTH TRACE_PTR - LENGTH KMT_PP_RECALL_DATA;
PP_TRACE_PTR(SIZE TRACE_CT) := TRACE_PTR(SIZE TRACE_CT);
PP_TRACE_COUNT := PP_TRACE_COUNT + TRACE_CT;
PP_TRACE_PTR := PP_TRACE_BUFFER(PP_TRACE_COUNT::);
KMT_FH_WRITE (RESULT) @ output record @
FI
ELSF
(LAST_CHAR_INDEX GE 0) AND (RECORD(LAST_CHAR_INDEX SIZE 2) EQ CRLF)
THEN @ EBCDIC or ASCII file xfer @
@ end of record, output it @
@ (obtain trace info) @
INT TRACE_CT := LENGTH TRACE_PTR - (LENGTH KMT_PP_RECALL_DATA + 2);
IF TRACE_CT = -1 @ CR LF split between two packets @
THEN
TRACE_CT := 0
ELSE
PP_TRACE_PTR(SIZE TRACE_CT) := TRACE_PTR(SIZE TRACE_CT);
FI;
PP_TRACE_PTR := PP_TRACE_BUFFER((PP_TRACE_COUNT + TRACE_CT)::);
PP_TRACE_PTR(SIZE 4) := X"202F2F20";
PP_TRACE_COUNT := PP_TRACE_COUNT + TRACE_CT + 4;
PP_TRACE_PTR := PP_TRACE_BUFFER(PP_TRACE_COUNT::);
RECORD_LENGTH := RECORD_SIZE - (LENGTH KMT_PP_RECALL_DATA + 2);
@ Don't want CRLF in file @
IF
TEXT_TYPE EQ EBCDIC
THEN @ EBCDIC file transfer @
TRANSLATE (ASCII_TO_EBCDIC,
RECORD(SIZE RECORD_LENGTH),
0,
NIL)
FI;
KMT_FH_WRITE (RESULT);
NEW_RECORD := TRUE
ELSF
(
RECORD_LENGTH := RECORD_SIZE - LENGTH KMT_PP_RECALL_DATA;
NEW_RECORD
)
THEN @ EBCDIC or ASCII file xfer @
@ and record buffer full but @
@ no end of record found. @
() KMT_MTM_VALUES PARAMS := DISPLAY(MAX_RECORD_LENGTH
AS KMT_MTM_VALUES.RI_VALUE);
RESULT := KMT_PP_RECORD_TOO_BIG;
KMT_EH_LOG_ERROR (RESULT,
2,
PARAMS,
0,
FALSE,
FALSE)
FI
REPEAT;
IF KMT_TRACE_FLAGS.PP_TRACING
THEN (<RARELY>)
(
IF DATA_COMPLETE AND NOT NEW_RECORD @ (obtain rest of trace info) @
THEN
INT TRACE_CT := LENGTH TRACE_PTR - LENGTH KMT_PP_RECALL_DATA;
PP_TRACE_PTR(SIZE TRACE_CT) := TRACE_PTR(SIZE TRACE_CT);
PP_TRACE_COUNT := PP_TRACE_COUNT + TRACE_CT
FI;
IF PP_TRACE_COUNT > 0
THEN
IF TEXT_TYPE NE BINARY
THEN
TRANSLATE(ASCII_TO_EBCDIC,
PP_TRACE_BUFFER(SIZE PP_TRACE_COUNT),
0,
NIL)
FI;
KMT_PP_DATA_TRACE_MESSAGE(KMT_PP_PACKET_DATA_IN_MSG,
TEXT_TYPE,
PP_TRACE_BUFFER(SIZE PP_TRACE_COUNT))
FI
)
FI
END; @ KMT_PP_BUILD_FILE_RECORD @
***PAGE
GLOBAL
STATIC (<STATUS 5>)
PROC
KMT_PP_BUILD_PARAM_PACKET_DATA IS ():
@******************************************************************************@
@* *@
@* This procedure is used to construct the packet data from the configuration *@
@* parameters. *@
@* The configuration parameters are read from the area *@
@* KMT_PP_LOCAL_CONFG_PARAMS and the packet data and length is returned in *@
@* the areas KMT_PP_OUTPUT_PACKET_DATA.DATA and *@
@* KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH respectively. *@
@* *@
@******************************************************************************@
BEGIN
REF () BYTE DATA IS KMT_PP_OUTPUT_PACKET_DATA.DATA;
BYTE N IS X"4E"; @ ASCII N @
DATA(0) := KMT_PP_LOCAL_CONFG_PARAMS.MAXL + X"20";
DATA(1) := KMT_PP_LOCAL_CONFG_PARAMS.TIME + X"20";
DATA(2) := KMT_PP_LOCAL_CONFG_PARAMS.NPAD + X"20";
DATA(3) := KMT_PP_LOCAL_CONFG_PARAMS.PADC NEQ X"40";
DATA(4) := KMT_PP_LOCAL_CONFG_PARAMS.EOL + X"20";
DATA(5) := KMT_PP_LOCAL_CONFG_PARAMS.QCTL;
DATA(6) := IF
KMT_FH_RECORD_DETAILS.TEXT_TYPE NE EBCDIC
THEN @ ASCII or binary file xfer @
@ requested, do 8th bit @
@ quoting @
KMT_PP_LOCAL_CONFG_PARAMS.QBIN
ELSE @ EBCDIC file transfer @
@ requested, donot do 8th bit @
@ quoting @
N
FI;
@ We don't support any others @
@ so default them @
KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH := 7;
IF KMT_TRACE_FLAGS.PP_TRACING
THEN (<RARELY>)
(
() INT P := (KMT_PP_LOCAL_CONFG_PARAMS.MAXL,
KMT_PP_LOCAL_CONFG_PARAMS.TIME,
KMT_PP_LOCAL_CONFG_PARAMS.NPAD);
() KMT_MTM_VALUES PARAMS := (P(0)
AS KMT_MTM_VALUES.RI_VALUE,
P(1)
AS KMT_MTM_VALUES.RI_VALUE,
P(2)
AS KMT_MTM_VALUES.RI_VALUE,
KMT_PP_LOCAL_CONFG_PARAMS.PADC
AS KMT_MTM_VALUES.RVB_VALUE,
KMT_PP_LOCAL_CONFG_PARAMS.EOL
AS KMT_MTM_VALUES.RVB_VALUE,
KMT_PP_LOCAL_CONFG_PARAMS.QCTL
AS KMT_MTM_VALUES.RVB_VALUE,
DATA(6)
AS KMT_MTM_VALUES.RVB_VALUE);
KMT_SP_LOG_TRACE_MESSAGE(KMT_PP_PARAM_OUT_MSG,PARAMS)
)
FI
END; @ KMT_PP_BUILD_PARAM_PACKET_DATA @
***PAGE
GLOBAL
STATIC (<STATUS 5>)
PROC
KMT_PP_PROCESS_PARAM_PACKET_DATA IS (
RESPONSE RESULT):
@******************************************************************************@
@* *@
@* This procedure is used to extract the configuration parameters from the *@
@* packet data. *@
@* The packet data is read from the area referenced by *@
@* KMT_PH_INPUT_PACKET_DATA and the configuration parameters are returned in *@
@* the area KMT_PP_REMOTE_CONFG_PARAMS. *@
@* *@
@******************************************************************************@
BEGIN
***PAGE
SIM
PROC
KMT_PP_LOG_PARAM_ERROR IS (
INT NAME_CODE,
REF () BYTE VALUE,
INT REASON_CODE,
RESPONSE RESULT):
@******************************************************************************@
@* *@
@* This procedure is used to log configuration parameter validation errors to *@
@* the job journal. *@
@* *@
@******************************************************************************@
BEGIN
INT KMT_PP_INVALID_CONFIG_PARAM IS 80257;
INT NAME := NAME_CODE,
REASON := REASON_CODE;
() KMT_MTM_VALUES PARAMS := (NAME
AS KMT_MTM_VALUES.RI_VALUE,
VALUE
AS KMT_MTM_VALUES.RVB_VALUE,
REASON
AS KMT_MTM_VALUES.RI_VALUE);
RESULT := KMT_PP_INVALID_CONFIG_PARAM;
KMT_EH_LOG_ERROR (RESULT,2,PARAMS,0,FALSE,FALSE)
END; @ KMT_PP_LOG_PARAM_ERROR @
***PAGE
INT KMT_PP_QBIN_AND_QCTL_EQUAL IS 80258,
KMT_PP_QCTL_WARNING IS -80259,
KMT_PP_QBIN_REJECTED IS 80260;
INT MAXL_CODE IS 0,
NPAD_CODE IS 1,
PADC_CODE IS 2,
EOL_CODE IS 3,
QCTL_CODE IS 4,
QBIN_CODE IS 5;
INT INFO_LENGTH IS SIZEOF KMT_PP_CONFG_PARAMS_S;
(INFO_LENGTH) BYTE PACKET_INFO;
WORD MAX_OUTPUT_LENGTH IS KMT_DH_DEVICE_DETAILS.MAX_OUTPUT_LENGTH;
WORD TEXT_TYPE IS KMT_FH_RECORD_DETAILS.TEXT_TYPE;
WORD MIN_PACKET_LENGTH IS 30;
INT DATA_LENGTH IS LENGTH KMT_PH_INPUT_PACKET_DATA;
REF BYTE MAXL IS KMT_PP_REMOTE_CONFG_PARAMS.MAXL,
TIME IS KMT_PP_REMOTE_CONFG_PARAMS.TIME,
NPAD IS KMT_PP_REMOTE_CONFG_PARAMS.NPAD,
PADC IS KMT_PP_REMOTE_CONFG_PARAMS.PADC,
EOL IS KMT_PP_REMOTE_CONFG_PARAMS.EOL,
QCTL IS KMT_PP_REMOTE_CONFG_PARAMS.QCTL,
QBIN IS KMT_PP_REMOTE_CONFG_PARAMS.QBIN,
CHKT IS KMT_PP_REMOTE_CONFG_PARAMS.CHKT,
REPT IS KMT_PP_REMOTE_CONFG_PARAMS.REPT;
REF 4-BYTE CAPAS IS KMT_PP_REMOTE_CONFG_PARAMS.CAPAS;
REF BYTE LOCAL_MARK IS KMT_PP_LOCAL_CONFG_PARAMS.MARK,
LOCAL_QCTL IS KMT_PP_LOCAL_CONFG_PARAMS.QCTL,
LOCAL_QBIN IS KMT_PP_LOCAL_CONFG_PARAMS.QBIN;
INT RC;
BYTE PARAM;
BYTE NUL IS X"00", @ ASCII NUL @
CR IS X"0D", @ CR @
SPACE IS X"20", @ Space @
HASH IS X"23", @ # @
ONE IS X"31", @ 1 @
RAB IS X"3E", @ > @
CTLNUL IS X"40", @ Controlled NUL @
N IS X"4E", @ N @
Y IS X"59", @ Y @
GRAVE IS X"60", @ ` @
TILDE IS X"7E", @ ~ @
DEL IS X"7F"; @ DEL @
RESULT := 0;
MOVEBYTE (SPACE, @ Set defaults @
PACKET_INFO,
0,
NIL);
PACKET_INFO(3) := CTLNUL; @ PADC default @
PACKET_INFO(SIZE DATA_LENGTH) := KMT_PH_INPUT_PACKET_DATA;
IF KMT_TRACE_FLAGS.PP_TRACING
THEN (<RARELY>)
(
() INT IP := (PACKET_INFO(0) - X"20",
PACKET_INFO(1) - X"20",
PACKET_INFO(2) - X"20",
PACKET_INFO(7) - X"30");
() BYTE BP := (PACKET_INFO(3) NEQ X"40",
PACKET_INFO(4) - X"20");
() KMT_MTM_VALUES PARAMS := (IP(0) @ MAXL @
AS KMT_MTM_VALUES.RI_VALUE,
IP(1) @ TIME @
AS KMT_MTM_VALUES.RI_VALUE,
IP(2) @ NPAD @
AS KMT_MTM_VALUES.RI_VALUE,
BP(0) @ PADC @
AS KMT_MTM_VALUES.RVB_VALUE,
BP(1) @ EOL @
AS KMT_MTM_VALUES.RVB_VALUE,
PACKET_INFO(5) @ QBIN @
AS KMT_MTM_VALUES.RVB_VALUE,
PACKET_INFO(6) @ QCTL @
AS KMT_MTM_VALUES.RVB_VALUE,
IP(3) @ CHKT @
AS KMT_MTM_VALUES.RI_VALUE,
PACKET_INFO(8) @ REPT @
AS KMT_MTM_VALUES.RVB_VALUE,
PACKET_INFO(9 SIZE 4) @ CAPAS @
AS KMT_MTM_VALUES.RVB_VALUE);
KMT_SP_LOG_TRACE_MESSAGE(KMT_PP_PARAM_IN_MSG,PARAMS(SIZE DATA_LENGTH))
)
FI;
PARAM := PACKET_INFO(0) - X"20";
MAXL := IF
(PARAM EQ 0)
OR
(PARAM GE MAX_OUTPUT_LENGTH)
THEN @ Defaulted or greater than @
@ device line length @
MAX_OUTPUT_LENGTH
ELSE
PARAM
FI;
TIME := PACKET_INFO(1) - X"20";
NPAD := PACKET_INFO(2) - X"20";
PADC := PACKET_INFO(3) NEQ X"40";
PARAM := PACKET_INFO(4) - X"20";
EOL := IF
PARAM EQ 0
THEN @ defaulted, set to CR @
CR
ELSE
PARAM
FI;
PARAM := PACKET_INFO(5);
QCTL := IF
PARAM EQ SPACE
THEN @ Defaulted, set to # @
HASH
ELSE
PARAM
FI;
PARAM := PACKET_INFO(6);
QBIN := IF
PARAM EQ N @ ASCII N @
THEN @ 8th bit quoting rejected @
SPACE
ELSF
PARAM EQ Y @ ASCII Y @
THEN @ 8th bit quoting requested @
LOCAL_QBIN
ELSE
PARAM
FI;
@ We donot support any others @
@ so default them @
CHKT := ONE;
REPT := NUL;
CAPAS := NUL;
@ Validate configuration @
@ parameters @
IF MAXL LT MIN_PACKET_LENGTH
THEN @ Invalid MAXL parameter @
KMT_PP_LOG_PARAM_ERROR (MAXL_CODE,MAXL,80270,RESULT)
FI;
IF (MAXL + NPAD) LE MAX_OUTPUT_LENGTH
THEN
SKIP
ELSF @ Device line length exceeded @
( @ Adjust MAXL @
MAXL := MAX_OUTPUT_LENGTH - NPAD;
MAXL LT MIN_PACKET_LENGTH
)
THEN @ NPAD parameter invalid @
KMT_PP_LOG_PARAM_ERROR (NPAD_CODE,NPAD,80271,RESULT)
FI;
IF (PADC GT SPACE) AND (PADC NE DEL)
THEN @ Invalid PADC character @
KMT_PP_LOG_PARAM_ERROR (PADC_CODE,PADC,80272,RESULT)
FI;
IF EOL = LOCAL_MARK
THEN @ EOL conflicts with MARK @
KMT_PP_LOG_PARAM_ERROR (EOL_CODE,EOL,80276,RESULT)
ELSF KMT_SP_CHECK_VME_CHAR(EOL,1,RC);
RC NE 0
THEN @ EOL not acceptable to VME @
KMT_PP_LOG_PARAM_ERROR (EOL_CODE,EOL,80274,RESULT)
FI;
IF NPAD > 0
THEN @ check for PADC conflict @
IF PADC = LOCAL_MARK
THEN @ PADC conflicts with MARK @
KMT_PP_LOG_PARAM_ERROR (PADC_CODE,PADC,80276,RESULT)
ELSF PADC = EOL
THEN @ PADC conflicts with EOL @
KMT_PP_LOG_PARAM_ERROR (PADC_CODE,PADC,80277,RESULT)
ELSF KMT_SP_CHECK_VME_CHAR(PADC,1,RC);
RC NE 0
THEN @ PADC not acceptable to VME @
KMT_PP_LOG_PARAM_ERROR (PADC_CODE,PADC,80274,RESULT)
FI
FI;
IF (QCTL LE SPACE) OR (QCTL GE DEL)
THEN @ Invalid QCTL character @
KMT_PP_LOG_PARAM_ERROR (QCTL_CODE,QCTL,80273,RESULT)
FI;
IF (QCTL GT RAB) AND (QCTL LT GRAVE)
THEN
@ KERMIT protocol permits the QCTL character to be any printable @
@ character. However a QCTL character value in the range X3F to X5F may @
@ result in data corruption. A warning message is logged but the choice @
@ of QCTL is permitted as the protocol allows it. eg Consider a QCTL @
@ character of '?' (X3F) and data containing the character DEL (X7F). @
@ The sender encodes this as a two byte sequence: QCTL (DEL XOR X40) @
@ ie '??' (X3F3F). The quoting rule states that QCTL caharacters @
@ appearing in the data must also be prefixed. Therefore the receiver @
@ will decode the sequence as '?' (X3F) not DEL (X7F) as required. @
BYTE CORRUPTED_CHAR := (QCTL NEQ X"40");
() KMT_MTM_VALUES PARAMS := (QCTL
AS KMT_MTM_VALUES.RVB_VALUE,
CORRUPTED_CHAR
AS KMT_MTM_VALUES.RVB_VALUE);
KMT_EH_LOG_ERROR (KMT_PP_QCTL_WARNING,2,PARAMS,0,FALSE,FALSE)
FI;
IF TEXT_TYPE EQ EBCDIC
THEN @ EBCDIC file transfer @
SKIP
ELSF
(QBIN LT SPACE)
OR
(QBIN GT TILDE)
OR
((QBIN GT RAB) AND (QBIN LT GRAVE))
THEN @ Invalid QBIN character @
KMT_PP_LOG_PARAM_ERROR (QBIN_CODE,QBIN,80275,RESULT)
ELSF
QBIN EQ SPACE
THEN @ QBIN character rejected @
RESULT := KMT_PP_QBIN_REJECTED;
KMT_EH_LOG_ERROR (RESULT,2,NIL,0,FALSE,FALSE)
ELSF
QBIN EQ QCTL OR QBIN EQ LOCAL_QCTL
THEN @ ASCII or binary file xfer, @
@ but QBIN and QCTL characters@
@ are equal @
() KMT_MTM_VALUES PARAMS := (QBIN
AS KMT_MTM_VALUES.RVB_VALUE,
QCTL
AS KMT_MTM_VALUES.RVB_VALUE,
LOCAL_QCTL
AS KMT_MTM_VALUES.RVB_VALUE);
RESULT := KMT_PP_QBIN_AND_QCTL_EQUAL;
KMT_EH_LOG_ERROR (RESULT,2,PARAMS,0,FALSE,FALSE)
ELSE @ IA5 or binary file transfer,@
@ and QCTL and QBIN characters@
@ are acceptable @
LOCAL_QBIN := QBIN
FI
END; @ KMT_PP_PROCESS_PARAM_PACKET_DATA @
ENDMODULE @ KMT_PP_MODULE @