VME KERMIT VERSION 1.01 ======================= The source files contained in this file are: KERMIT : SCL interface procedure KMT_DATA_MODULE : S3 modules KMT_DH_MODULE KMT_EH_MODULE KMT_FH_MODULE KMT_MAIN_MODULE KMT_PH_MODULE KMT_PP_MODULE KMT_SP_MODULE KMT_UI_MODULE KMT_HELP_MTM : Message Text Modules KMT_SP_MTM Each file is preceded by $$$$ $$$$ KERMIT @******************************************************************************@ @ @ @ VME Kermit User Interface Procedure. @ @ ------------------------------------ @ @ @ @ Installation instructions: @ @ @ @ 1. The BOOL value ASG should be set to TRUE if terminal connection @ @ to VME is via ASG, otherwise set to FALSE (for CSC, NIC etc). @ @ @ @ 2. The default option may be changed from "COMMAND" to "SERVER" if @ @ desired. @ @ @ @******************************************************************************@ PROC KERMIT IS ( LITERAL (OPTION) OPT := "COMMAND", @ "SERVER" is a valid alternative @ LITERAL (VME_FILE) VF := "", LITERAL (REM_FILE) RF := "", RESPONSE (RESPONSE) R := RESULT) PROCBEGIN EXT PROC KERMIT_THE_FROG IS ( LITERAL OPTION := "COMMAND", @ DON'T change this to "SERVER" @ LITERAL VME_FILE := "", LITERAL REM_FILE := "", RESPONSE RESPONSE := RESULT) BOOL ASG IS FALSE @ TRUE : comms route is via ASG, FALSE : via CSC or NIC @ KERMIT_THE_FROG(VAL OPT,VAL VF,VAL RF,R) PROCEND $$$$ KMT_DATA_MODULE MODULE KMT_DATA_MODULE; () @******************************************************************************@ @* *@ @* Mode definitions *@ @* *@ @******************************************************************************@ MODE KMT_FH_RECORD_DETAILS_S IS STRUCT ( BOOL FILE_OPEN, NEW_RECORD, END_OF_FILE, WORD TEXT_TYPE, @ 0 = EBCDIC @ @ 1 = IA5 @ @ 2 = BINARY @ INT MAX_RECORD_LENGTH, RECORD_LENGTH, (4098) BYTE RECORD); @ Maximum record size of @ @ 4096 + 2 bytes for CRLF @ @ pair when constructing @ @ output records @ MODE KMT_FH_FILE_STATISTICS_S IS STRUCT ( INT INPUT_TOTAL, INT OUTPUT_TOTAL); 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_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_TRACE_FLAGS_S IS WORD STRUCT ( BIT PH_TRACING, PP_TRACING, FH_TRACING, DH_TRACING, 28-BIT SPARE); MODE KMT_STATISTICS_FLAGS_S IS WORD STRUCT ( BIT PP_STATISTICS, FH_STATISTICS, 30-BIT SPARE); MODE KMT_STATISTICS_S IS STRUCT ( REF KMT_FH_FILE_STATISTICS_S FH_FILE_STATISTICS, REF KMT_PP_PACKET_STATISTICS_S PACKET_STATISTICS); MODE KMT_BUFFER IS (96)BYTE; MODE KMT_STRING IS REF()BYTE; MODE KMT_WORD IS REF()BYTE; 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 @******************************************************************************@ @* *@ @* Global data declarations *@ @* *@ @******************************************************************************@ @ Constants: @ @ ********** @ GLOBAL STATIC (256) BYTE ASCII_TO_EBCDIC IS X"00010203 372D2E2F 1605250B 0C0D0E0F" X"10111213 3C3D3226 18193F27 1C1D1E1F" X"404F7F7B 5B6C507D 4D5D5C4E 6B604B61" X"F0F1F2F3 F4F5F6F7 F8F97A5E 4C7E6E6F" X"7CC1C2C3 C4C5C6C7 C8C9D1D2 D3D4D5D6" X"D7D8D9E2 E3E4E5E6 E7E8E94A E05A5F6D" X"79818283 84858687 88899192 93949596" X"979899A2 A3A4A5A6 A7A8A9C0 6AD0A107" X"00010203 372D2E2F 1605250B 0C0D0E0F" X"10111213 3C3D3226 18193F27 1C1D1E1F" X"404F7F7B 5B6C507D 4D5D5C4E 6B604B61" X"F0F1F2F3 F4F5F6F7 F8F97A5E 4C7E6E6F" X"7CC1C2C3 C4C5C6C7 C8C9D1D2 D3D4D5D6" X"D7D8D9E2 E3E4E5E6 E7E8E94A E05A5F6D" X"79818283 84858687 88899192 93949596" X"979899A2 A3A4A5A6 A7A8A9C0 6AD0A107"; GLOBAL STATIC (256) BYTE EBCDIC_TO_ASCII IS X"00010203 1A091A7F 1A1A1A0B 0C0D0E0F" X"10111213 1AFB081A 18191A1A 1C1D1E1F" X"FFFEFDFC 1A0A171B 1A1A1A1A 1A050607" X"1A1A161A 1A1A1A04 1A1A1A1A 14151A1A" X"201A1A1A 1A1A1A1A 1A1A5B2E 3C282B21" X"261A1A1A 1A1A1A1A 1A1A5D24 2A293B5E" X"2D2F1A1A 1A1A1A1A 1A1A7C2C 255F3E3F" X"1A1A1A1A 1A1A1A1A 1A603A23 40273D22" X"1A616263 64656667 68691A1A 1A1A1A1A" X"1A6A6B6C 6D6E6F70 71721A1A 1A1A1A1A" X"1A7E7374 75767778 797A1A1A 1A1A1A1A" X"1A1A1A1A 1A1A1A1A 1A1A1A1A 1A1A1A1A" X"7B414243 44454647 48491A1A 1A1A1A1A" X"7D4A4B4C 4D4E4F50 51521A1A 1A1A1A1A" X"5C1A5354 55565758 595A1A1A 1A1A1A1A" X"30313233 34353637 38391A1A 1A1A1A1A"; GLOBAL STATIC INT UNSET IS -1, @ Kermit exit states @ EXIT IS 0, LOGOUT IS 1, FATAL_ERROR IS 999; GLOBAL STATIC INT EOF IS 9034; GLOBAL STATIC BOOL NOREADINT IS FALSE, READINT IS TRUE; GLOBAL STATIC INT SERVER_MODE IS 0, @ Kermit modes @ RECEIVE_MODE IS 1, SEND_MODE IS 2, COMMAND_MODE IS 3; GLOBAL STATIC INT REC_SERVER_IDLE IS 0, @ Protocol Handler states @ REC_INIT IS 1, REC_FILE IS 2, REC_DATA IS 3, SEND_INIT IS 4, SEND_FILE IS 5, SEND_DATA IS 6, SEND_EOF IS 7, SEND_BREAK IS 8, COMPLETE IS 9, ABORT IS 10; GLOBAL STATIC INT ENTRY IS 0, @ Packet codes @ BREAK_PKT IS 1, DATA_PKT IS 2, ERROR_PKT IS 3, FILE_HDR_PKT IS 4, GEN_CMD_PKT IS 5, INIT_PARAM_PKT IS 6, KMT_CMD_PKT IS 7, NAK_PKT IS 8, REC_INIT_PKT IS 9, SEND_INIT_PKT IS 10, ACK_PKT IS 11, EOF_PKT IS 12, BAD_PKT IS 13, INVALID_PKT IS 14; GLOBAL STATIC INT UNS_PKT IS -80251, @ Unsupported packet @ NON_PKT IS -80252; @ Non-existant packet type @ GLOBAL STATIC () INT PACKET_CODES := (UNS_PKT, BREAK_PKT, @ B packet @ UNS_PKT, DATA_PKT, @ D packet @ ERROR_PKT, @ E packet @ FILE_HDR_PKT, @ F packet @ GEN_CMD_PKT, @ G packet @ NON_PKT, INIT_PARAM_PKT, @ I packet @ NON_PKT, KMT_CMD_PKT, @ K packet @ NON_PKT, NON_PKT, NAK_PKT, @ N packet @ NON_PKT, NON_PKT, NON_PKT, REC_INIT_PKT, @ R packet @ SEND_INIT_PKT, @ S packet @ UNS_PKT, NON_PKT, NON_PKT, NON_PKT, UNS_PKT, ACK_PKT, @ Y packet @ EOF_PKT); @ Z packet @ GLOBAL STATIC INT VME_TERM IS 0, @ VME terminal file name @ VME_STD IS 1, @ VME standard file name @ KMT_STD IS 2; @ Kermit standard name @ ***LINES(4) @ Variables: @ @ ********** @ GLOBAL STATIC () KMT_FH_RECORD_DETAILS_S KMT_FH_RECORD_DETAILS; GLOBAL STATIC () KMT_FH_FILE_STATISTICS_S KMT_FH_FILE_STATISTICS; GLOBAL STATIC () KMT_DH_DEVICE_DETAILS_S KMT_DH_DEVICE_DETAILS; ***LINES(4) GLOBAL STATIC () KMT_PP_CONFG_PARAMS_S KMT_PP_LOCAL_CONFG_PARAMS; GLOBAL STATIC () KMT_PP_CONFG_PARAMS_S KMT_PP_REMOTE_CONFG_PARAMS; GLOBAL STATIC () KMT_PP_PACKET_STATISTICS_S KMT_PP_PACKET_STATISTICS; ***LINES(4) GLOBAL STATIC () REF () BYTE KMT_PH_INPUT_PACKET_DATA; ***LINES(4) GLOBAL STATIC () KMT_TRACE_FLAGS_S KMT_TRACE_FLAGS; GLOBAL STATIC () KMT_STATISTICS_FLAGS_S KMT_STATISTICS_FLAGS; GLOBAL STATIC () KMT_STATISTICS_S KMT_STATISTICS := (KMT_FH_FILE_STATISTICS, KMT_PP_PACKET_STATISTICS); GLOBAL STATIC () BYTE KMT_VERSION := "1.01"; GLOBAL STATIC BOOL ASG_ROUTE; GLOBAL STATIC (15)KMT_MTM_VALUES KMT_MTM_AREA; GLOBAL STATIC (80)BYTE MTM_TEXT; GLOBAL STATIC INT MTM_TEXT_LEN; GLOBAL STATIC (2)REF()BYTE MTM_RECALL_DATA; GLOBAL STATIC INT RC_IGNORED; @ ignored result code @ GLOBAL STATIC INT PKT_SEQ; @ packet sequence number @ GLOBAL STATIC INT PKT_NO; @ number of packet received @ GLOBAL STATIC INT PKT_TYPE; @ packet type @ GLOBAL STATIC INT RETRY_COUNT; @ retry count @ GLOBAL STATIC INT RETRY_TOTAL; @ total retries during xfer @ GLOBAL STATIC INT TIMEOUT_TOTAL; @ total timeouts during xfer @ GLOBAL STATIC INT MAXTRY; @ max retries @ GLOBAL STATIC INT EXIT_STATE; @ controls main Kermit loop @ GLOBAL STATIC INT KMT_CURRENT_MODE; @ server/send/receive/command @ GLOBAL STATIC INT KMT_PH_STATE; @ state in protocol handler @ GLOBAL STATIC INT FILE_OPTION; @ create or replace receive files @ GLOBAL STATIC WORD DELAY; @ time delay before SEND_INIT packet@ GLOBAL STATIC BOOL DELAY_TIMER; @ set delay timer before get packet @ GLOBAL STATIC BOOL SAVE_INCOMPLETE_FILE; @ save action for incomplete files @ GLOBAL STATIC BOOL TRANSLATE_FILENAME; @ file names to be translated @ GLOBAL STATIC KMT_BUFFER KMT_VME_FILE_BUF, @ buffer for VME filename @ KMT_REM_FILE_BUF; @ buffer for remote filename @ GLOBAL STATIC KMT_WORD KMT_VME_FILE, @ pointer to VME filename @ KMT_REM_FILE; @ pointer to remote filename @ GLOBAL STATIC KMT_BUFFER KMT_INPUT_BUF; @ command line buffer@ ***LINES(4) @ Results: @ @ ******** @ ***LINES(4) ENDMODULE @ KMT_DATA_MODULE @ $$$$ KMT_DH_MODULE MODULE KMT_DH_MODULE; @******************************************************************************@ @* *@ @* Mode definitions *@ @* *@ @******************************************************************************@ MODE PFI_REPORTS IS LONG WORD STRUCT ( 4-BIT ALWAYS_ZERO, 12-BIT USER_FILE_IDENT, TRANSFER_IDENTIFIER, 4-BIT REASON, BYTE QUALIFIER_1, QUALIFIER_2, 2-BYTE CHARACTER_OUTPUT); MODE PFI_FLAGS_1S IS BYTE STRUCT ( BIT MEDIUM_LOW, DATA_LOST, FORMAT_DISTURBED, PERMANENTLY_UNAVAILABLE, TEMPORARILY_UNAVAILABLE, NOT_IMPLEMENTED, GENERAL_FILE_FREEZE, CHARACTER_OUTPUT_VALID); MODE PFI_FLAGS_2S IS BYTE STRUCT ( BIT PROPERTIES_LOST, LONG_LINE, ILLEGAL_DATA, FILE_TIMEOUT, 4-BIT SPARE); MODE PFI_INPUT_FLAGS IS 2-BYTE STRUCT ( BIT QUALIFIED, 15-BIT SPARE); MODE PFI_INPUT_RETURNS IS WORD STRUCT ( PFI_INPUT_FLAGS INPUT_FLAGS, 2-BYTE DATA_LENGTH); MODE PFI_QUEUE_CONTROLS IS WORD STRUCT ( BIT BREAK_IN, DATA_LOST, FORMAT_DISTURBED, BREAK_IN_ACK, GENERAL_FILE_FREEZE, RESET, 26-BIT RESERVED); MODE PFI_OUTPUT_CONTROLS IS WORD STRUCT ( BIT EXPIDITED_DATA, REPORT_NORMAL_TERMINATION, PROMPT, CANCEL_OUTSTANDING_PROMPT, OVERRIDE_MY_READ_INTEREST, SPARE_2, QUALIFIED, SEQUENCE, BYTE COMMAND, 2-BYTE SPARE5); MODE PFI_FILE_FLAGS IS WORD STRUCT ( BIT FORMAT_SENSITIVE, ACTION_KEY_IS_DATA, AUTOPAGING, AUTOMATIC_NEW_LINE, BADGE_REQUIRED, PAUSING_REQUIRED, INHIBIT_SPACE_TRUNCATION, INHIBIT_SPACE_COMPRESSION, FE_AT_START_OF_RECORD, REJECT_ILLEGAL_DATA, ALLOW_COMPRESSION, 21-BIT RESERVED); MODE PFI_PARAMETER_VALUES IS ANY ( INT INT_VALUE, PFI_FILE_FLAGS FILE_FLAGS, REF REF () BYTE RRRB_VALUE, REF () BYTE STRING_VALUE); MODE PFI_PARAMETER_PAIRS IS STRUCT ( WORD TYPE, PFI_PARAMETER_VALUES VALUE); MODE KMT_TRACE_FLAGS_S IS WORD STRUCT ( BIT PH_TRACING, PP_TRACING, FH_TRACING, DH_TRACING, 28-BIT SPARE); 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_DH_FILE_DETAILS_S IS STRUCT ( LONG INT FILE_CURRENCY, WORD PFM_CURRENCY, CONNECTION_CURRENCY, TIMER_CHANNEL, BOOL READ_INTEREST, (2) WORD EVENT_LIST, BOOL LONG_SUSPEND); MODE KMT_PP_CONFG_PARAMS_S IS STRUCT ( BYTE MARK, MAXL, TIME, NPAD, PADC, EOL, QCTL, QBIN, CHKT, REPT, 4-BYTE CAPAS); 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 (LONG WORD, @ FILE_CURRENCY @ REF () BYTE, @ FILE_LOCAL_NAME @ REF () BYTE, @ FULL_FILE_NAME @ REF () WORD, @ PROPERTIES @ RESPONSE @ RESPONSE @ ) CTM_READ_DESC; EXT () PROC (WORD, @ TIME_INTERVAL @ RESPONSE @ RESPONSE @ ) CTM_WAIT_TIME; EXT () PROC (REF () BYTE, @ NAME @ REF LONG INT, @ LNAME @ REF () BYTE, @ ACCESS @ REF () BYTE, @ LEVEL @ REF () BYTE, @ LOCK @ REF () BYTE, @ REUSE @ LONG INT, @ STARTSECT @ LONG INT, @ ENDSECT @ LONG INT, @ LOAD @ REF () REF () BYTE, @ DNAMES @ RESPONSE @ RESPONSE @ ) ASSIGN_FILE; EXT () PROC (INT, @ EVENT_NODE_CURRENCY @ BYTE, @ ACCESS @ BYTE, @ SHARABILITY @ REF WORD, @ EVENT_CURRENCY @ LONG WORD, @ INTERRUPT_PROC @ WORD, @ SPARE @ RESPONSE @ RESPONSE @ ) CONNECT_EVENT; EXT () PROC (WORD, @ EVENT_CURRENCY @ LONG WORD, @ MESSAGE @ INT, @ REPLY @ RESPONSE @ RESPONSE @ ) READ_EVENT; EXT () PROC (LONG WORD, @ FILE_CURRENCY @ REF WORD, @ PFM_CURRENCY @ REF WORD, @ CONNECTION_CURRENCY @ REF () BYTE, @ DETAILS_SUPPLIED @ REF () BYTE, @ DETAILS_REQUIRED @ REF () BYTE, @ DETAILS_RETURNED @ RESPONSE @ RESPONSE @ ) BI_CONNECT_FILE; EXT () PROC (WORD, @ CONNECTION_CURRENCY @ REF () BYTE, @ DETAILS_SUPPLIED @ REF () BYTE, @ DETAILS_REQUIRED @ REF () BYTE, @ DETAILS_RETURNED @ RESPONSE @ RESPONSE @ ) BI_MODIFY_CONNECTION; EXT () PROC (REF () WORD, @ EVENT_LIST @ REF WORD, @ EVENT_CURRENCY @ REF LONG WORD, @ MESSAGE @ BOOL, @ LONG_SUSPEND @ RESPONSE @ RESPONSE @ ) WAIT_FOR_EVENTS; EXT () PROC (WORD, @ EVENT_CURRENCY @ REF WORD, @ TIMER_CHANNEL @ RESPONSE @ RESPONSE @ ) CREATE_TIMER_CHANNEL; EXT () PROC (WORD, @ TIMER_CHANNEL @ LONG WORD, @ MESSAGE @ LONG INT, @ TIME @ BOOL, @ REAL_TIME @ BOOL, @ PERIODIC @ RESPONSE) @ RESPONSE @ ESTABLISH_TIMER_NOTIFICATION; EXT () PROC (WORD, @ TIMER_CHANNEL @ RESPONSE @ RESPONSE @ ) CANCEL_TIMER_NOTIFICATION; EXT () PROC (WORD, @ PFM_CURRENCY @ WORD, @ START_OF_INPUT @ REF () BYTE, @ BUFFER @ REF PFI_INPUT_RETURNS, @ INPUT_RETURN @ RESPONSE @ RESPONSE @ ) DH_INPUT; EXT () PROC (WORD, @ PFM_CURRENCY @ WORD, @ TRANSFER_IDENTIFIER @ REF () BYTE, @ OUTPUT_DATA @ PFI_OUTPUT_CONTROLS, @ CONTROL @ RESPONSE @ RESPONSE @ ) DH_OUTPUT; EXT () PROC (WORD, @ PFM_CURRENCY @ REF () PFI_PARAMETER_PAIRS, @ PARAMS @ RESPONSE @ RESPONSE @ ) DH_DEFINE_FILE_PROPERTIES; EXT () PROC (WORD, @ PFM_CURRENCY @ WORD, @ QUEUE_ACTION @ PFI_QUEUE_CONTROLS, @ CONTROL @ REF () BYTE, @ ADDITIONAL_DATA @ RESPONSE @ RESPONSE @ ) DH_DO_QUEUE_ACTION; EXT () PROC (WORD, @ PFM_CURRENCY @ REF () BYTE, @ DETAILS_REQUIRED @ REF () BYTE, @ DETAILS_AREA @ REF WORD, @ DETAILS_LENGTH_AREA @ RESPONSE @ RESPONSE @ ) DH_GIVE_FILE_DETAILS; EXT PROC (INT, @ TYPE @ REF () KMT_MTM_VALUES @ PARAMS @ ) KMT_SP_LOG_TRACE_MESSAGE; 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; ***PAGE @******************************************************************************@ @* *@ @* External data references *@ @* *@ @******************************************************************************@ @ Constants: @ @ ********** @ ***LINES(4) @ Variables: @ @ ********** @ EXT () REF KMT_TRACE_FLAGS_S KMT_TRACE_FLAGS; EXT () REF KMT_DH_DEVICE_DETAILS_S KMT_DH_DEVICE_DETAILS; EXT () REF KMT_PP_CONFG_PARAMS_S KMT_PP_REMOTE_CONFG_PARAMS; EXT () REF BOOL DELAY_TIMER; EXT () REF WORD DELAY; ***LINES(4) @ Results: @ @ ******** @ ***LINES(4) ***PAGE @******************************************************************************@ @* *@ @* Static data declarations *@ @* *@ @******************************************************************************@ @ Constants: @ @ ********** @ ***LINES(4) @ Variables: @ @ ********** @ STATIC KMT_DH_FILE_DETAILS_S KMT_DH_FILE_DETAILS; ***PAGE @******************************************************************************@ @* *@ @* Procedure declarations *@ @* *@ @******************************************************************************@ STATIC PROC KMT_DH_PROCESS_RESPONSE IS ( INT RESULTCODE, BOOL PROMPT, REF BOOL RETRY, RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to process resultcodes returned from COSMAN and to *@ @* handle CDH events. *@ @* RETRY is set TRUE if a recoverable I/O error occurs indicating that the *@ @* I/O operation should be repeated. *@ @* PROMPT should be set TRUE if this is an output request and read interest *@ @* is required. *@ @* *@ @******************************************************************************@ BEGIN INT PFI_REQUEST_ACCEPTED IS -31008, PFI_FILE_FROZEN IS -38982, PFI_DELAYED_TRANSFER IS -38983, PFI_FILE_UNAVAILABLE IS 30978, PFI_OVERLOAD IS 37560, PFI_TEMPORARILY_UNAVAILABLE IS 37561, PFI_TIMED_OUT IS 39854; INT KMT_DH_EVENT_MSG IS 152, KMT_DH_UNEXPECTED_BREAKIN IS 80150, KMT_DH_UNEXPECTED_EVENT IS 80151, KMT_DH_INPUT_AVAILABLE IS -80152, KMT_DH_QUEUE_EMPTY IS -80153; REF BOOL READ_INTEREST IS KMT_DH_FILE_DETAILS.READ_INTEREST; BOOL TRACING IS KMT_TRACE_FLAGS.DH_TRACING; UNLESS READ_INTEREST OR RESULTCODE EQ PFI_REQUEST_ACCEPTED OR RESULTCODE EQ PFI_FILE_FROZEN OR RESULTCODE EQ PFI_DELAYED_TRANSFER OR RESULTCODE EQ PFI_OVERLOAD OR RESULTCODE EQ PFI_TEMPORARILY_UNAVAILABLE THEN @ Unrecoverable I/O error or @ @ REPORT NORMAL TERMINATION @ @ not set @ READ_INTEREST := FALSE; RESULT := RESULTCODE ELSE REF () WORD EVENT_LIST IS KMT_DH_FILE_DETAILS.EVENT_LIST; BOOL LONG_SUSPEND IS KMT_DH_FILE_DETAILS.LONG_SUSPEND; PFI_REPORTS EVENT_MESSAGE; REF PFI_FLAGS_1S QUALIFIER_1 IS EVENT_MESSAGE.QUALIFIER_1; REF PFI_FLAGS_2S QUALIFIER_2 IS EVENT_MESSAGE.QUALIFIER_2; REF WORD PFM_CURRENCY IS KMT_DH_FILE_DETAILS.PFM_CURRENCY; READ_INTEREST := FALSE; RESULT := 0; WHILE @ Process CDH event @ ( INT RC_DISCARDED; WORD EVENT_CURRENCY; BOOL SUSPEND := FALSE; RETRY := FALSE; WAIT_FOR_EVENTS (EVENT_LIST(SIZE 1), EVENT_CURRENCY, EVENT_MESSAGE, LONG_SUSPEND, RC_DISCARDED); IF TRACING THEN () ( () KMT_MTM_VALUES PARAMS := DISPLAY(EVENT_MESSAGE AS KMT_MTM_VALUES.RLW_VALUE); KMT_SP_LOG_TRACE_MESSAGE (KMT_DH_EVENT_MSG, PARAMS) ) FI; IF QUALIFIER_1.DATA_LOST THEN DH_DO_QUEUE_ACTION (PFM_CURRENCY, 0, @ Unfreeze @ X'40000000', NIL, RC_DISCARDED); RETRY := TRUE FI; IF QUALIFIER_1.FORMAT_DISTURBED THEN DH_DO_QUEUE_ACTION (PFM_CURRENCY, 0, @ Unfreeze @ X'20000000', NIL, RC_DISCARDED); RETRY := TRUE FI; IF QUALIFIER_1.PERMANENTLY_UNAVAILABLE THEN RESULT := PFI_FILE_UNAVAILABLE FI; IF QUALIFIER_1.TEMPORARILY_UNAVAILABLE THEN SUSPEND := TRUE FI; IF QUALIFIER_1.GENERAL_FILE_FREEZE THEN DH_DO_QUEUE_ACTION (PFM_CURRENCY, 0, @ Unfreeze @ X'08000000', NIL, RC_DISCARDED); RETRY := TRUE FI; IF QUALIFIER_2.FILE_TIMEOUT THEN RESULT := PFI_TIMED_OUT FI; UNLESS RETRY OR RESULT NE 0 THEN CASE EVENT_MESSAGE.REASON THEN @ 0 - PFI_NORMAL_TERM @ READ_INTEREST := PROMPT ELSE @ 1 - PFI_ABNORMAL_TERM @ RETRY := TRUE ELSE @ 2 - PFI_ATTENTION @ SUSPEND := TRUE ELSE @ 3 - PFI_FILE_AVAILABLE @ RETRY := (RESULTCODE NE PFI_DELAYED_TRANSFER); SUSPEND := NOT(RETRY) ELSE @ 4 - PFI_INPUT_AVAILABLE @ RESULT := KMT_DH_INPUT_AVAILABLE ELSE () @ 5 - PFI_ACTION_KEY @ ( RESULT := KMT_DH_UNEXPECTED_BREAKIN; KMT_EH_LOG_ERROR (RESULT, 2, NIL, 0, TRUE, @ Produce UCG dump @ FALSE) @ Recoverable @ ) ELSE @ 6 - PFI_PROMPT_CANCELLED @ RETRY := TRUE ELSE @ 7 - PFI_QUEUE_EMPTY @ RETRY := FALSE; RESULT := KMT_DH_QUEUE_EMPTY DEFAULT () @ Unexpected event from CDH @ ( RESULT := KMT_DH_UNEXPECTED_EVENT; KMT_EH_LOG_ERROR (RESULT, 2, NIL, 0, TRUE, @ Produce UCG dump @ FALSE) @ Recoverable @ ) ESAC FI; SUSPEND AND RESULT EQ 0 ) DO SKIP REPEAT FI END; @ KMT_DH_PROCESS_RESPONSE @ ***PAGE GLOBAL STATIC () PROC KMT_DH_OPEN_FILE IS ( RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to assign, connect and open an interactive file *@ @* with read and write capability. *@ @* The interactive file is assigned to the slow file description :STD.STDMAC *@ @* and uses code set 255 (transparent 7-bit ISO). *@ @* The file will be used for the exchange of KERMIT packets. *@ @* *@ @******************************************************************************@ BEGIN INT KMT_EH_SOFTWARE_ERROR IS 80101; REF LONG INT FILE_CURRENCY IS KMT_DH_FILE_DETAILS.FILE_CURRENCY; REF WORD PFM_CURRENCY IS KMT_DH_FILE_DETAILS.PFM_CURRENCY; REF () WORD EVENT_LIST IS KMT_DH_FILE_DETAILS.EVENT_LIST; IF ( () BYTE NAME := ":STD.STDMAC", ACCESS := "W", LEVEL := "R", LOCK := "", REUSE := "NO", DNAME := "ICL9NINTDEVICE"; () REF () BYTE DNAMES := DISPLAY (DNAME); ASSIGN_FILE (NAME, FILE_CURRENCY, ACCESS, LEVEL, LOCK, REUSE, -5, -5, 0, DNAMES, RESULT); RESULT LE 0 ) AND ( CONNECT_EVENT (0, X"C0", X"C0", EVENT_LIST(0), 0, 0, RESULT); RESULT LE 0 ) AND ( () BYTE DETAILS_SUPPLIED := X"CE080000000000000000"; EVENT_LIST(1) := EVENT_LIST(0); DETAILS_SUPPLIED(2 SIZE 4) := 4-BYTE: EVENT_LIST(0); DETAILS_SUPPLIED(6 SIZE 4) := 4-BYTE: EVENT_LIST(1); BI_CONNECT_FILE (FILE_CURRENCY, PFM_CURRENCY, KMT_DH_FILE_DETAILS.CONNECTION_CURRENCY, DETAILS_SUPPLIED, NIL, NIL, RESULT); RESULT LE 0 ) AND ( INT FILE_CLASS IS 11, @ PFI_INTERACTIVE @ CODE_SET IS 255, @ Transparent 7-bit ISO @ TIME_OUT IS 0; @ No TIMEOUT ie indefinite @ @ wait @ PFI_FILE_FLAGS FILE_FLAGS IS X'03000000'; @ Inhibit space truncation @ @ Inhibit space compression @ () PFI_PARAMETER_PAIRS PARAMS := ((X'00', FILE_CLASS AS PFI_PARAMETER_VALUES.INT_VALUE), (X'01', CODE_SET AS PFI_PARAMETER_VALUES.INT_VALUE), (X'02', FILE_FLAGS AS PFI_PARAMETER_VALUES.FILE_FLAGS), (X'18', TIME_OUT AS PFI_PARAMETER_VALUES.INT_VALUE) ); KMT_DH_FILE_DETAILS.READ_INTEREST := FALSE; WHILE ( BOOL RETRY; DH_DEFINE_FILE_PROPERTIES (PFM_CURRENCY, PARAMS, RESULT); KMT_DH_PROCESS_RESPONSE (RESULT, FALSE, RETRY, RESULT); RETRY ) DO SKIP REPEAT; RESULT LE 0 ) AND @ Timeout intervals may be @ @ set in multiples of 2 @ @ minutes using the PFI. @ @ We need to be able to set @ @ timeout intervals in the @ @ order of 5 to 30 seconds. @ @ Therefore we must set up @ @ our own timer channel. @ ( CREATE_TIMER_CHANNEL (EVENT_LIST(0), KMT_DH_FILE_DETAILS.TIMER_CHANNEL, RESULT); RESULT LE 0 ) THEN @ File opened successfully @ () WORD PROPERTIES := (104, @ Maximum record size @ 0, 0); () BYTE DETAILS_REQUIRED := X"49" @ Line length @ X"51"; @ Suspension advice @ (6) BYTE DETAILS_AREA; KMT_DH_DEVICE_DETAILS.MAX_INPUT_LENGTH := IF ( CTM_READ_DESC (FILE_CURRENCY, NIL, NIL, PROPERTIES, RESULT); RESULT EQ 0 ) THEN PROPERTIES(1) ELSE 80 FI; DH_GIVE_FILE_DETAILS (PFM_CURRENCY, DETAILS_REQUIRED, DETAILS_AREA, NIL, RESULT); IF RESULT EQ 0 THEN KMT_DH_DEVICE_DETAILS.MAX_OUTPUT_LENGTH := DETAILS_AREA(2); KMT_DH_FILE_DETAILS.LONG_SUSPEND := BIT:DETAILS_AREA(5) ELSE KMT_DH_DEVICE_DETAILS.MAX_OUTPUT_LENGTH := 80; KMT_DH_FILE_DETAILS.LONG_SUSPEND := TRUE FI FI; IF RESULT GT 0 THEN () @ Open error @ ( () BYTE PROC_NAME := "KMT_DH_OPEN_FILE"; () KMT_MTM_VALUES PARAMS := DISPLAY(PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE); KMT_DH_DEVICE_DETAILS.FILE_OPEN := FALSE; KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) ELSE @ Ignore warnings @ KMT_DH_DEVICE_DETAILS.FILE_OPEN := TRUE; RESULT := 0 FI END; @ KMT_DH_OPEN_FILE @ ***PAGE GLOBAL STATIC () PROC KMT_DH_CLOSE_FILE IS ( RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to close the file previously opened by the *@ @* procedure KMT_DH_OPEN_FILE. *@ @* *@ @******************************************************************************@ BEGIN INT KMT_EH_SOFTWARE_ERROR IS 80101; REF BOOL FILE_OPEN IS KMT_DH_DEVICE_DETAILS.FILE_OPEN; RESULT := 0; IF FILE_OPEN THEN @ File open, close it @ INT RC_DISCARDED; IF ( () BYTE DETAILS_SUPPLIED := DISPLAY (181,@ FC_TI_ACTION_TYPE @ 1, @ Length @ 40);@ FC_DI_DISCONNECT @ BI_MODIFY_CONNECTION (KMT_DH_FILE_DETAILS.CONNECTION_CURRENCY, DETAILS_SUPPLIED, NIL, NIL, RESULT); RESULT GT 0 ) THEN () @ Close error @ ( () BYTE PROC_NAME := "KMT_DH_CLOSE_FILE"; () KMT_MTM_VALUES PARAMS := DISPLAY(PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE); KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) ELSE @ Ignore warnings @ RESULT := 0 FI; FILE_OPEN := FALSE; FI END; @ KMT_DH_CLOSE_FILE @ ***PAGE GLOBAL STATIC () PROC KMT_DH_OUTPUT IS ( REF () BYTE OUTPUT_PACKET, BOOL PROMPT, RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to send a KERMIT packet to the remote end. The *@ @* end of line terminating character and any padding characters are added and *@ @* the required parity is set. *@ @* OUTPUT_PACKET references an area containing the packet to be output. *@ @* If the length of the output packet is zero then a single 'PAD' character *@ @* is output. If PROMPT is set true then the procedure will set read *@ @* interest on the file for the next call to KMT_DH_INPUT. *@ @* *@ @******************************************************************************@ BEGIN ***PAGE SIM PROC KMT_DH_SET_PARITY IS ( REF () BYTE BUFFER): @******************************************************************************@ @* *@ @* This procedure is used to set the required parity for each byte contained *@ @* in BUFFER. *@ @* *@ @******************************************************************************@ BEGIN WORD PARITY IS KMT_DH_DEVICE_DETAILS.OUTPUT_PARITY; IF PARITY LE 1 THEN @ Even or odd parity required @ BYTE INITIAL_PARITY_MASK IS IF PARITY EQ 0 THEN @ Even parity @ X"80" ELSE @ Odd parity @ X"00" FI; FOR I TO BOUND BUFFER DO BYTE PARITY_MASK := INITIAL_PARITY_MASK; WORD THIS_BYTE := BUFFER(I) & X"7F"; WHILE ( INT NUM_BITS_SHIFTED; THIS_BYTE := SHWZ (THIS_BYTE, NUM_BITS_SHIFTED); THIS_BYTE NE 0 ) DO PARITY_MASK := PARITY_MASK NEQ X"80"; THIS_BYTE := THIS_BYTE & X'7F000000' REPEAT; BUFFER(I) := BUFFER(I) ! PARITY_MASK REPEAT ELSF PARITY EQ 2 THEN @ Mark parity @ ORBYTE (X"80", BUFFER, 0, NIL) ELSF PARITY EQ 3 THEN @ Space parity @ ANDBYTE (X"7F", BUFFER, 0, NIL) FI END; @ KMT_DH_SET_PARITY @ ***PAGE INT PFI_REQUEST_ACCEPTED IS -31008, PFI_TIMED_OUT IS 39854; INT KMT_DH_DATA_OUT_MSG IS 151, KMT_DH_INPUT_AVAILABLE IS -80152, KMT_DH_QUEUE_EMPTY IS -80153; INT KMT_EH_SOFTWARE_ERROR IS 80101; INT NPAD IS KMT_PP_REMOTE_CONFG_PARAMS.NPAD; INT OUTPUT_PACKET_LENGTH IS IF OUTPUT_PACKET IS NIL THEN 0 ELSE LENGTH OUTPUT_PACKET FI; INT OUTPUT_BUFFER_LENGTH IS IF OUTPUT_PACKET_LENGTH EQ 0 THEN 1 ELSE OUTPUT_PACKET_LENGTH + NPAD + 1 FI; PFI_OUTPUT_CONTROLS CONTROL IS IF PROMPT THEN @ Report normal termination @ @ Prompt @ X'60000000' ELSE @ Report normal termination @ X'40000000' FI; WORD PFM_CURRENCY IS KMT_DH_FILE_DETAILS.PFM_CURRENCY; (OUTPUT_BUFFER_LENGTH) BYTE OUTPUT_BUFFER; BOOL TRACING IS KMT_TRACE_FLAGS.DH_TRACING; INT RC_DISCARDED; IF OUTPUT_PACKET_LENGTH EQ 0 THEN @ No packet supplied, @ @ output single PAD character @ OUTPUT_BUFFER := KMT_PP_REMOTE_CONFG_PARAMS.PADC; ELSE @ Build output data buffer @ @ consisting of the required @ @ number of PAD characters, @ @ the packet and the @ @ end of line terminating @ @ character @ INT EOL IS IF KMT_PP_REMOTE_CONFG_PARAMS.EOL = X"0D" @ ASG converts CR @ THEN X"0A" @ to NULL, LF to CRLF - fix also works via NIC @ ELSE KMT_PP_REMOTE_CONFG_PARAMS.EOL FI; MOVEBYTE (KMT_PP_REMOTE_CONFG_PARAMS.PADC, OUTPUT_BUFFER(SIZE NPAD), 0, NIL); OUTPUT_BUFFER(NPAD SIZE OUTPUT_PACKET_LENGTH) := OUTPUT_PACKET; OUTPUT_BUFFER(OUTPUT_BUFFER_LENGTH - 1) := EOL FI; KMT_DH_SET_PARITY (OUTPUT_BUFFER); CTM_WAIT_TIME (KMT_DH_DEVICE_DETAILS.PAUSE, @ Wait before sending packet @ RC_DISCARDED); WHILE ( BOOL RETRY; @ Ensure no I/O requests are @ @ outstanding @ DH_DO_QUEUE_ACTION (PFM_CURRENCY, 5, @ PFI_ABORT_QUEUE @ 0, NIL, RESULT); WHILE ( KMT_DH_PROCESS_RESPONSE (RESULT, FALSE, RETRY, RESULT); RETRY OR (RESULT EQ KMT_DH_INPUT_AVAILABLE) OR (RESULT EQ PFI_TIMED_OUT) ) DO RESULT := PFI_REQUEST_ACCEPTED REPEAT; IF RESULT EQ KMT_DH_QUEUE_EMPTY THEN @ File queue empty @ RESULT := 0 FI; IF RESULT LE 0 THEN @ File queue emptied @ @ successfilly @ IF TRACING THEN () ( () KMT_MTM_VALUES PARAMS := DISPLAY(OUTPUT_BUFFER AS KMT_MTM_VALUES.RVB_VALUE); KMT_SP_LOG_TRACE_MESSAGE (KMT_DH_DATA_OUT_MSG, PARAMS) ) FI; DH_OUTPUT (PFM_CURRENCY, @ Send output data @ 0, OUTPUT_BUFFER, CONTROL, RESULT); KMT_DH_PROCESS_RESPONSE (RESULT, @ Check if successful @ PROMPT, RETRY, RESULT); FI; RETRY ) DO SKIP REPEAT; IF RESULT GT 0 THEN () @ I/O error @ ( () BYTE PROC_NAME := "KMT_DH_OUTPUT"; () KMT_MTM_VALUES PARAMS := DISPLAY(PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE); KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) ELSE @ Ignore warnings @ RESULT := 0 FI END; @ KMT_DH_OUTPUT @ ***PAGE GLOBAL STATIC () PROC KMT_DH_INPUT IS ( REF () BYTE INPUT_BUFFER, REF INT INPUT_BUFFER_LENGTH, RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to receive an input buffer from the remote end. *@ @* The input buffer may or may not contain a valid KERMIT packet. *@ @* The input buffer and length are returned in the areas referenced by *@ @* INPUT_BUFFER and INPUT_BUFFER_LENGTH respectively. *@ @* *@ @******************************************************************************@ BEGIN ***PAGE SIM PROC KMT_DH_REMOVE_PARITY IS ( REF () BYTE BUFFER): @******************************************************************************@ @* *@ @* This procedure is used to remove the parity bit (if present) for each byte *@ @* in BUFFER. *@ @* *@ @******************************************************************************@ BEGIN @ Clear parity bit @ ANDBYTE (X"7F", @ 7 bit IA5 @ BUFFER, 0, NIL) END; @ KMT_DH_REMOVE_PARITY @ ***PAGE INT TIM_NO_NOTIFICATIONS IS -32156, PFI_MESSAGE_CANCELLED IS 38575, PFI_TIMED_OUT IS 39854; INT KMT_DH_DATA_IN_MSG IS 150, KMT_EH_SOFTWARE_ERROR IS 80101, KMT_DH_INPUT_AVAILABLE IS -80152; PFI_INPUT_RETURNS INPUT_RETURN; BOOL TRACING IS KMT_TRACE_FLAGS.DH_TRACING; WORD TIMER_CHANNEL IS KMT_DH_FILE_DETAILS.TIMER_CHANNEL; WORD TIME IS IF DELAY_TIMER THEN DELAY ELSE KMT_PP_REMOTE_CONFG_PARAMS.TIME FI; IF ( RESULT := 0; UNLESS KMT_DH_FILE_DETAILS.READ_INTEREST THEN @ Read interest not set. @ @ Set read interest @ KMT_DH_OUTPUT (NIL, TRUE, RESULT) FI; RESULT LE 0 ) AND ( IF TIME NE 0 THEN @ Timeout intervals may be @ @ set in multiples of 2 @ @ minutes using the PFI. @ @ We need to be able to set @ @ timeout intervals in the @ @ order of 5 to 30 seconds. @ @ Therefore we must set up @ @ our own timer channel. @ LONG INT TIME_IN_MSECS IS (L'I'TIME) * 1000000; ESTABLISH_TIMER_NOTIFICATION (TIMER_CHANNEL, X'00000000 00100000', @ File timeout @ @ Make it look like a PFI @ @ timeout @ TIME_IN_MSECS + I'CLOCKTIME (), TRUE, FALSE, RESULT) FI; RESULT LE 0 ) AND ( INT RC_DISCARDED; BOOL RETRY; KMT_DH_PROCESS_RESPONSE (RESULT, @ Wait for PFI event @ FALSE, RETRY, RESULT); IF (TIME NE 0) AND (RESULT NE PFI_TIMED_OUT) AND @ Timeout set but timeout @ ( @ event did not occur. @ @ Turn off timer. @ CANCEL_TIMER_NOTIFICATION (TIMER_CHANNEL, RC_DISCARDED); RC_DISCARDED EQ TIM_NO_NOTIFICATIONS ) THEN @ Timeout event occurred @ @ after PFI event but before @ @ the timer could be @ @ cancelled. @ @ Read the timeout event and @ @ discarded it. @ LONG WORD EVENT_MESSAGE; INT REPLY; READ_EVENT (KMT_DH_FILE_DETAILS.EVENT_LIST(0), EVENT_MESSAGE, REPLY, RC_DISCARDED) FI; RESULT EQ KMT_DH_INPUT_AVAILABLE ) AND ( WORD PFM_CURRENCY IS KMT_DH_FILE_DETAILS.PFM_CURRENCY; DH_INPUT (PFM_CURRENCY, @ Get input data @ 0, INPUT_BUFFER, INPUT_RETURN, RESULT); RESULT LE 0 ) THEN @ Input data read @ INPUT_BUFFER_LENGTH := INPUT_RETURN.DATA_LENGTH; IF (INPUT_BUFFER(INPUT_BUFFER_LENGTH - 1) & X"7F") EQ X"1E" THEN @ Via a PAD and using @ @ code set 255 RS (X1E) is @ @ appended to the end of the @ @ record by VME. Ignore it. @ INPUT_BUFFER_LENGTH := INPUT_BUFFER_LENGTH - 1 FI; IF TRACING THEN () ( () KMT_MTM_VALUES PARAMS := DISPLAY(INPUT_BUFFER(SIZE INPUT_BUFFER_LENGTH) AS KMT_MTM_VALUES.RVB_VALUE); KMT_SP_LOG_TRACE_MESSAGE (KMT_DH_DATA_IN_MSG, PARAMS) ) FI; KMT_DH_REMOVE_PARITY (INPUT_BUFFER(SIZE INPUT_BUFFER_LENGTH)); ELSE INPUT_BUFFER_LENGTH := 0 FI; IF RESULT EQ PFI_MESSAGE_CANCELLED THEN @ 'CANCEL' key, ignore RC @ RESULT := 0 FI; IF (RESULT GT 0) AND (RESULT NE PFI_TIMED_OUT) THEN () @ I/O error @ ( () BYTE PROC_NAME := "KMT_DH_INPUT"; () KMT_MTM_VALUES PARAMS := DISPLAY(PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE); KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) ELSF RESULT LE 0 THEN @ Ignore warnings @ RESULT := 0 FI END; @ KMT_DH_INPUT @ ENDMODULE @ KMT_DH_MODULE @ $$$$ KMT_EH_MODULE MODULE KMT_EH_MODULE; @******************************************************************************@ @* *@ @* Mode definitions *@ @* *@ @******************************************************************************@ 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 (INT, @ ERROR_NUMBER @ REF () BYTE, @ ERROR_MESSAGE @ REF INT, @ MESSAGE_LENGTH @ RESPONSE @ RESPONSE @ ) CTM_GIVE_ERROR_MSG; EXT () PROC (WORD, @ TYPE @ WORD, @ DESTINATION @ REF () BYTE, @ MESSAGE @ RESPONSE @ RESPONSE @ ) CTM_LOG; EXT () PROC (LONG LONG WORD, @ TARGET_RESPONSE @ INT @ RESPONSE_TO_CTM_JS_CALL @ ) CTM_STOP; EXT () PROC (LONG WORD, @ MESSAGE @ WORD, @ FRAMES @ WORD, @ PLTS @ REF () LONG WORD, @ ADDRESSES @ REF () REF () BYTE, @ AREAS @ WORD, @ OPTIONS @ RESPONSE @ RESPONSE @ ) CTM_DUMP; EXT () PROC (WORD, @ CONTINGENCY_CLASS @ LONG WORD, @ INTERRUPT_PROCEDURE @ RESPONSE @ RESPONSE @ ) CTM_INFORM; EXT PROC (INT, @ TEXT_NUMBER @ REF () KMT_MTM_VALUES @ AREA @ ) INT KMT_SP_MTM; ***PAGE @******************************************************************************@ @* *@ @* External data references *@ @* *@ @******************************************************************************@ @ Constants: @ @ ********** @ ***LINES(4) @ Variables: @ @ ********** @ EXT REF () BYTE KMT_DATA_AREA; ***LINES(4) @ Results: @ @ ******** @ ***LINES(4) ***PAGE @******************************************************************************@ @* *@ @* Procedure declarations *@ @* *@ @******************************************************************************@ GLOBAL STATIC () PROC KMT_EH_LOG_ERROR IS ( INT RESULTCODE, WORD DESTINATION, REF () KMT_MTM_VALUES PARAMS, LONG WORD PE_CONTINGENCY_MESSAGE, BOOL DUMP, BOOL UNRECOVERABLE): @******************************************************************************@ @* *@ @* This procedure is used to log failing resultcodes to the job journal *@ @* and/or to the MAC screen and to produce UCG dumps. *@ @* If RESULTCODE is non zero then a failure message will be generated using *@ @* the parameters in the list referenced by PARAMS and logged to the job *@ @* journal. *@ @* If DUMP is set TRUE then a UCG dump is produced. PE_CONTINGENCY_MESSAGE is *@ @* used in conjunction with DUMP and must contain either zero or a program *@ @* error contingency message. *@ @* If UNRECOVERABLE is set TRUE then the program will exit. *@ @* *@ @******************************************************************************@ BEGIN INT KMT_EH_SOFTWARE_ERROR IS 80101, KMT_EH_ICL_RESULT IS 80102; INT RC_DISCARDED, MESSAGE_LENGTH; (120) BYTE ERROR_MESSAGE; REF () BYTE MESSAGE_REM; UNLESS RESULTCODE EQ 0 THEN INT RC IS IF RESULTCODE LT 0 THEN -RESULTCODE ELSE RESULTCODE FI; BOOL ICL_RESULTCODE IS ((RC LT 80000) OR (RC GT 89999)); INT PARAMS_LENGTH IS IF PARAMS IS NIL THEN 0 ELSE LENGTH PARAMS FI; INT MTM_AREA_LENGTH IS PARAMS_LENGTH + IF ICL_RESULTCODE THEN 5 ELSE 4 FI; (MTM_AREA_LENGTH) KMT_MTM_VALUES MTM_AREA; INT MTM_TEXT_NUMBER, MTM_REPLY, MTM_MESSAGE_LENGTH; (100) BYTE MTM_MESSAGE; (2) REF () BYTE MTM_RECALL_DATA; MTM_AREA (SIZE 4) := (MTM_MESSAGE AS KMT_MTM_VALUES.RVB_VALUE, MTM_MESSAGE_LENGTH AS KMT_MTM_VALUES.RI_VALUE, MTM_RECALL_DATA AS KMT_MTM_VALUES.RVRVB_VALUE, (L'PARAMS_LENGTH) AS KMT_MTM_VALUES.LI_VALUE); IF ICL_RESULTCODE THEN @ Use MTM text number @ @ KMT_EH_ICL_RESULT to expand @ @ the error message passing @ @ the RESULTCODE as a @ @ parameter @ MTM_TEXT_NUMBER := KMT_EH_ICL_RESULT; MTM_AREA(4) := (L'RESULTCODE) AS KMT_MTM_VALUES.LI_VALUE; IF PARAMS_LENGTH GT 0 THEN MTM_AREA(5::) := PARAMS FI ELSE @ Use RESULTCODE as the MTM @ @ text number to expand the @ @ error message @ MTM_TEXT_NUMBER := RC; IF PARAMS_LENGTH GT 0 THEN MTM_AREA(4::) := PARAMS FI FI; WHILE ( MTM_REPLY := KMT_SP_MTM (MTM_TEXT_NUMBER, MTM_AREA); IF MTM_REPLY NE -2 THEN @ Expanded message returned @ REF () BYTE MESSAGE IS IF MTM_REPLY EQ -3 THEN @ Returned in recall data @ MTM_TEXT_NUMBER := 0; MTM_RECALL_DATA(0) ELSE @ Returned in message buffer @ MTM_TEXT_NUMBER := MTM_REPLY; MTM_MESSAGE(SIZE MTM_MESSAGE_LENGTH) FI; CTM_LOG (3, DESTINATION, MESSAGE, RC_DISCARDED) ELSE MTM_TEXT_NUMBER := 0 FI; MTM_TEXT_NUMBER NE 0 ) DO SKIP REPEAT; IF ICL_RESULTCODE @ Get ICL message text @ AND ( CTM_GIVE_ERROR_MSG (RC, ERROR_MESSAGE, MESSAGE_LENGTH, RC_DISCARDED); RC_DISCARDED EQ 0 ) AND MESSAGE_LENGTH GT 10 @ Skip "**** ERROR " @ AND ( MESSAGE_REM := ERROR_MESSAGE(10 SIZE MESSAGE_LENGTH - 10); NOT SCANUNQ (X'40', @ Look for start of text @ MESSAGE_REM, 0, MESSAGE_REM) ) THEN @ Message text exists for @ @ resultcode. Log to journal. @ CTM_LOG (3, DESTINATION, MESSAGE_REM, RC_DISCARDED) FI FI; IF DUMP THEN () LONG WORD ADDRESSES := DISPLAY (BDESC KMT_DATA_AREA); CTM_DUMP (PE_CONTINGENCY_MESSAGE, 10, 10, ADDRESSES, NIL, 4, @ Dump in character and hex @ RC_DISCARDED) FI; IF UNRECOVERABLE THEN CTM_STOP (L'L'W' RESULTCODE, -KMT_EH_SOFTWARE_ERROR) FI END; @ KMT_EH_LOG_ERROR @ ***PAGE GLOBAL STATIC () PROC KMT_EH_PE_CONTINGENCY_HANDLER IS ( REF LONG WORD PE_CONTINGENCY_MESSAGE): @******************************************************************************@ @* *@ @* This procedure is used to handle program error contingencies. The procedure*@ @* calls KMT_EH_LOG_ERROR to produce a UCG dump. All programs are treated as *@ @* unrecoverable. *@ @* PE_CONTINGENCY_MESSAGE references an area containing the program error *@ @* contingency message. *@ @* *@ @******************************************************************************@ BEGIN INT KMT_EH_SOFTWARE_ERROR IS 80101; KMT_EH_LOG_ERROR (KMT_EH_SOFTWARE_ERROR, 2, NIL, PE_CONTINGENCY_MESSAGE, TRUE, @ Produce UCG dump @ TRUE) @ Unrecoverable - Exit @ END; @ KMT_EH_PE_CONTINGENCY_HANDLER @ ***PAGE GLOBAL STATIC () PROC KMT_EH_INFORM_PE_CONTINGENCY IS ( RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to associate the contingency procedure: *@ @* KMT_EH_PE_CONTINGENCY_HANDLER with the the program error contingcy class. *@ @* *@ @******************************************************************************@ BEGIN INT KMT_EH_SOFTWARE_ERROR IS 80101; CTM_INFORM (X'80000000', @ PE contingencies @ PDESC KMT_EH_PE_CONTINGENCY_HANDLER, RESULT); IF RESULT GT 0 THEN () ( () BYTE PROC_NAME := "KMT_EH_INFORM_PE_CONTINGENCY"; () KMT_MTM_VALUES PARAMS := DISPLAY(PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE); KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) ELSE @ Ignore warnings @ RESULT := 0 FI END; @ KMT_EH_INFORM_PE_CONTINGENCY @ ENDMODULE @ KMT_EH_MODULE @ $$$$ KMT_FH_MODULE MODULE KMT_FH_MODULE; @******************************************************************************@ @* *@ @* Mode definitions *@ @* *@ @******************************************************************************@ MODE CTM_ACCESS_1 IS GPROC ( REF () CTM_PARAMETER_PAIRS, RESPONSE); MODE CTM_ACCESS_2 IS GPROC ( RESPONSE); MODE CTM_PARAMETER_VALUES IS ANY ( INT INT_VALUE, LONG WORD LONG_WORD_VALUE, REF INT REF_INT_VALUE, REF () BYTE STRING_VALUE, REF CTM_ACCESS_1 REF_ACCESS_1_VALUE, REF CTM_ACCESS_2 REF_ACCESS_2_VALUE); MODE CTM_PARAMETER_PAIRS IS WSTRUCT ( INT TYPE, CTM_PARAMETER_VALUES VALUE); MODE KMT_TRACE_FLAGS_S IS WORD STRUCT ( BIT PH_TRACING, PP_TRACING, FH_TRACING, DH_TRACING, 28-BIT SPARE); MODE KMT_FH_FILE_OPTIONS_S IS BYTE STRUCT ( BIT APPEND_CREATE, APPEND, REPLACE_CREATE, REPLACE, CREATE_APPEND, CREATE_REPLACE, CREATE, READ); MODE KMT_FH_RECORD_DETAILS_S IS STRUCT ( BOOL FILE_OPEN, NEW_RECORD, END_OF_FILE, WORD TEXT_TYPE, @ 0 = EBCDIC @ @ 1 = IA5 @ @ 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_FH_FILE_STATISTICS_S IS STRUCT ( INT INPUT_TOTAL, INT OUTPUT_TOTAL); MODE KMT_FH_FILE_DETAILS_S IS STRUCT ( LONG WORD FILE_CURRENCY, BOOL NEW_FILE, KMT_FH_FILE_OPTIONS_S FILE_OPTION, CTM_ACCESS_1 ACCESS_1, CTM_ACCESS_2 ACCESS_2); 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 LONG WORD, @ FILE_CURRENCY @ REF () BYTE, @ FILE_LOCAL_NAME @ REF () BYTE, @ FULL_FILE_NAME @ RESPONSE @ RESPONSE @ ) CTM_ASSIGN_FILE; EXT () PROC (REF LONG WORD, @ NEW_FILE_CURRENCY @ REF () BYTE, @ NEW_FILE_LOCAL_NAME @ LONG WORD, @ FILE_CURRENCY, @ REF () BYTE, @ FILE_LOCAL_NAME @ REF () BYTE, @ FULL_FILE_NAME @ LONG WORD, @ DESCRIPTION_CURRENCY @ REF () BYTE, @ DESCRIPTION_LOCAL_NAME @ REF () BYTE, @ FULL_DESCRIPTION_NAME @ INT, @ INITIAL_SIZE @ INT, @ MAXIMUM_SIZE @ INT, @ OPTION @ RESPONSE @ RESPONSE @ ) CTM_GET_FILE; EXT () PROC (LONG WORD, @ FILE_CURRENCY @ REF () BYTE, @ FILE_LOCAL_NAME @ RESPONSE @ RESPONSE @ ) CTM_SAVE_FILE; EXT () PROC (LONG WORD, @ FILE_CURRENCY @ REF () BYTE, @ FILE_LOCAL_NAME @ REF () BYTE, @ FULL_FILE_NAME @ REF () WORD, @ PROPERTIES @ RESPONSE @ RESPONSE @ ) CTM_READ_DESC; EXT () PROC (RESPONSE @ RESPONSE @ ) CTM_SCHEDULE; EXT () PROC (LONG WORD, @ FILE_CURRENCY @ REF () BYTE, @ FILE_LOCAL_NAME @ REF () CTM_PARAMETER_PAIRS, @ PARAMETER_PAIRS @ RESPONSE @ RESPONSE @ ) CTM_SELECT_RAM; EXT () PROC (LONG WORD, @ FILE_CURRENCY @ REF () BYTE, @ FILE_LOCAL_CURRENCY @ REF () BYTE, @ FULL_FILE_NAME @ REF INT, @ NAME_LENGTH @ RESPONSE @ RESPONSE @ ) CTM_GIVE_NAME; EXT PROC (INT, @ TYPE @ REF () KMT_MTM_VALUES @ PARAMS @ ) KMT_SP_LOG_TRACE_MESSAGE; 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; ***PAGE @******************************************************************************@ @* *@ @* External data references *@ @* *@ @******************************************************************************@ @ Constants: @ @ ********** @ ***LINES(4) @ Variables: @ @ ********** @ EXT () REF KMT_TRACE_FLAGS_S KMT_TRACE_FLAGS; EXT () REF KMT_FH_RECORD_DETAILS_S KMT_FH_RECORD_DETAILS; EXT () REF KMT_FH_FILE_STATISTICS_S KMT_FH_FILE_STATISTICS; ***LINES(4) @ Results: @ @ ******** @ ***LINES(4) ***PAGE @******************************************************************************@ @* *@ @* Static data declarations *@ @* *@ @******************************************************************************@ @ Constants: @ @ ********** @ ***LINES(4) @ Variables: @ @ ********** @ STATIC KMT_FH_FILE_DETAILS_S KMT_FH_FILE_DETAILS; ***LINES(4) @ Results: @ @ ******** @ ***LINES(4) ***PAGE @******************************************************************************@ @* *@ @* Procedure declarations *@ @* *@ @******************************************************************************@ GLOBAL STATIC () PROC KMT_FH_OPEN_FILE IS ( REF () BYTE FILE_NAME, WORD OPTION, RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to create (if required), assign and open the data *@ @* file specified by FILE_NAME for read or write access depending upon the *@ @* value of OPTION. *@ @* *@ @******************************************************************************@ BEGIN INT FC_CTM_FILE_ALREADY_EXISTS IS 9113, FC_CTM_FILE_DOES_NOT_EXIST IS 9114, FC_CTM_NEW_FILE_WARNING IS -44900; INT KMT_EH_SOFTWARE_ERROR IS 80101; REF LONG WORD FILE_CURRENCY IS KMT_FH_FILE_DETAILS.FILE_CURRENCY; REF KMT_FH_FILE_OPTIONS_S FILE_OPTION IS KMT_FH_FILE_DETAILS.FILE_OPTION; FILE_OPTION := (WORD: X'01') SCALE OPTION; IF ( IF FILE_OPTION.READ THEN @ Read @ CTM_ASSIGN_FILE (FILE_CURRENCY, NIL, FILE_NAME, RESULT) ELSE @ Write @ CTM_GET_FILE (FILE_CURRENCY, NIL, 0, NIL, FILE_NAME, 0, NIL, NIL, -1, -1, (IF (FILE_OPTION & X"0E") NE 0 THEN @ Create, create_replace or @ @ create_append @ 0 ELSE @ Replace, replace_create, @ @ append or append_create @ 2 FI), RESULT); IF (RESULT EQ 0) AND FILE_OPTION.CREATE THEN @ Create but file already @ @ exists @ RESULT := FC_CTM_FILE_ALREADY_EXISTS ELSF (RESULT EQ FC_CTM_NEW_FILE_WARNING) AND (FILE_OPTION & X"50" NE 0) THEN @ Replace or append but file @ @ does not exist @ RESULT := FC_CTM_FILE_DOES_NOT_EXIST FI FI; KMT_FH_FILE_DETAILS.NEW_FILE := (RESULT EQ FC_CTM_NEW_FILE_WARNING); RESULT LE 0 ) AND ( CTM_SCHEDULE (RESULT); RESULT LE 0 ) AND ( () CTM_PARAMETER_PAIRS PARAMETER_PAIRS := ((7, KMT_FH_RECORD_DETAILS.RECORD AS CTM_PARAMETER_VALUES.STRING_VALUE), (9, KMT_FH_RECORD_DETAILS.RECORD_LENGTH AS CTM_PARAMETER_VALUES.REF_INT_VALUE), (12, (IF FILE_OPTION.READ THEN @ Read @ 1 @ Select and read @ ELSE @ Write @ 2 @ Select and new write @ FI) AS CTM_PARAMETER_VALUES.INT_VALUE), (19, KMT_FH_FILE_DETAILS.ACCESS_2 AS CTM_PARAMETER_VALUES.REF_ACCESS_2_VALUE), (24, KMT_FH_FILE_DETAILS.ACCESS_1 AS CTM_PARAMETER_VALUES.REF_ACCESS_1_VALUE), (29, (IF (FILE_OPTION & X"C8") NE 0 THEN @ Append @ 3 @ End of file @ ELSE @ Read, create or replace @ 2 @ Beginning of file @ FI) AS CTM_PARAMETER_VALUES.INT_VALUE) ); CTM_SELECT_RAM (FILE_CURRENCY, NIL, PARAMETER_PAIRS, RESULT); RESULT LE 0 ) AND ( IF (FILE_OPTION & X"34") NE 0 THEN @ Replacing file, @ @ destroy file contents @ () CTM_PARAMETER_PAIRS PARAMETER_PAIRS := DISPLAY((0, 11 @ Extended destroy @ AS CTM_PARAMETER_VALUES.INT_VALUE) ); KMT_FH_FILE_DETAILS.ACCESS_1 (PARAMETER_PAIRS, RESULT) FI; RESULT LE 0 ) THEN WORD R_LEN IS LENGTH KMT_FH_RECORD_DETAILS.RECORD - 2; @ Allows for CRLF end of @ @ record terminator @ () WORD PROPERTIES := (104, @ Maximum record size @ 0, 0); KMT_FH_RECORD_DETAILS.MAX_RECORD_LENGTH := IF ( CTM_READ_DESC ( FILE_CURRENCY, NIL, NIL, PROPERTIES, RESULT); RESULT EQ 0 ) AND PROPERTIES(1) LT R_LEN THEN PROPERTIES(1) ELSE R_LEN FI FI; IF RESULT LE 0 THEN @ File opened successfully @ KMT_FH_RECORD_DETAILS.FILE_OPEN := TRUE; KMT_FH_RECORD_DETAILS.NEW_RECORD := TRUE; KMT_FH_RECORD_DETAILS.END_OF_FILE := FALSE; KMT_FH_FILE_STATISTICS := (0,0); RESULT := 0 @ Ignore warnings @ ELSE () @ Open error @ ( () BYTE PROC_NAME := "KMT_FH_OPEN_FILE"; () KMT_MTM_VALUES PARAMS := DISPLAY(PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE); KMT_FH_RECORD_DETAILS.FILE_OPEN := FALSE; KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) FI END; @ KMT_FH_OPEN_FILE @ ***PAGE GLOBAL STATIC () PROC KMT_FH_CLOSE_FILE IS ( RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to close the file previously opened by the *@ @* KMT_FH_OPEN_FILE. *@ @* *@ @******************************************************************************@ BEGIN INT KMT_EH_SOFTWARE_ERROR IS 80101; REF BOOL FILE_OPEN IS KMT_FH_RECORD_DETAILS.FILE_OPEN; RESULT := 0; IF FILE_OPEN THEN @ File open, close it @ INT RC; () CTM_PARAMETER_PAIRS PARAMETER_PAIRS := DISPLAY((0, 12 @ Deselect RAM @ AS CTM_PARAMETER_VALUES.INT_VALUE) ); @ When receiving a binary @ @ file, must output last @ @ record to file @ IF KMT_FH_FILE_DETAILS.FILE_OPTION.READ OR KMT_FH_RECORD_DETAILS.TEXT_TYPE NE 2 OR KMT_FH_RECORD_DETAILS.NEW_RECORD THEN @ File open for reading, not @ @ a binary file or @ RC := 0 @ no record to output @ ELSE @ Flush remaining buffer @ KMT_FH_WRITE (RC) FI; IF ( KMT_FH_FILE_DETAILS.ACCESS_1 (PARAMETER_PAIRS, RESULT); RESULT GT 0 ) THEN () @ Close error @ ( () BYTE PROC_NAME := "KMT_FH_CLOSE_FILE"; () KMT_MTM_VALUES PARAMS := DISPLAY(PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE); KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) ELSE RESULT := RC FI; FILE_OPEN := FALSE FI END; @ KMT_FH_CLOSE_FILE @ ***PAGE GLOBAL STATIC () PROC KMT_FH_READ IS ( RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to read a record from the file previously opened *@ @* (for read access) by the procedure KMT_FH_OPEN_FILE. *@ @* The record and length are returned in the areas *@ @* KMT_FH_RECORD_DETAILS.RECORD and KMT_FH_RECORD.DETAILS.RECORD_LENGTH *@ @* respectively. *@ @* *@ @******************************************************************************@ BEGIN INT DML_READ_PSEUDO_NODE IS 9034; INT KMT_FH_RECORD_IN_MSG IS 200, KMT_EH_SOFTWARE_ERROR IS 80101, KMT_FH_RECORD_TOO_BIG IS 80200; REF INT RECORD_LENGTH IS KMT_FH_RECORD_DETAILS.RECORD_LENGTH; REF () BYTE RECORD IS KMT_FH_RECORD_DETAILS.RECORD; IF ( KMT_FH_FILE_DETAILS.ACCESS_2 (RESULT); RESULT LE 0 ) THEN @ Read successful @ REF INT MAX_RECORD_LENGTH IS KMT_FH_RECORD_DETAILS.MAX_RECORD_LENGTH; BOOL TRACING IS KMT_TRACE_FLAGS.FH_TRACING; REF INT STATISTICS IS KMT_FH_FILE_STATISTICS.INPUT_TOTAL; STATISTICS := STATISTICS + 1; IF RECORD_LENGTH GT MAX_RECORD_LENGTH THEN () @ Record exceeds buffer size @ ( () KMT_MTM_VALUES PARAMS := (RECORD_LENGTH AS KMT_MTM_VALUES.RI_VALUE, MAX_RECORD_LENGTH AS KMT_MTM_VALUES.RI_VALUE); RESULT := KMT_FH_RECORD_TOO_BIG; KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RECORD_LENGTH := MAX_RECORD_LENGTH ) ELSE @ Ignore warnings @ RESULT := 0 FI; IF TRACING THEN () ( () KMT_MTM_VALUES PARAMS := DISPLAY(RECORD(SIZE RECORD_LENGTH) AS KMT_MTM_VALUES.RVB_VALUE); KMT_SP_LOG_TRACE_MESSAGE (KMT_FH_RECORD_IN_MSG, PARAMS) ) FI ELSF ( RECORD_LENGTH := 0; RESULT EQ DML_READ_PSEUDO_NODE ) THEN @ End of file reached @ SKIP ELSE () @ Read error @ ( () BYTE PROC_NAME := "KMT_FH_READ"; () BYTE ERROR_TEXT := " WHILST READING FROM FILE"; () KMT_MTM_VALUES PARAMS := (PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE, ERROR_TEXT AS KMT_MTM_VALUES.RVB_VALUE); KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) FI END; @ KMT_FH_READ @ ***PAGE GLOBAL STATIC () PROC KMT_FH_WRITE IS ( RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to write a record to the file previously opened *@ @* (for write access) by the procedure KMT_FH_OPEN_FILE. *@ @* The record to be output and length are contained in the areas *@ @* KMT_FH_RECORD_DETAILS.RECORD and KMT_FH_RECORD_DETAILS.RECORD_LENGTH *@ @* respectively. *@ @* *@ @******************************************************************************@ BEGIN INT KMT_FH_RECORD_OUT_MSG IS 201, KMT_EH_SOFTWARE_ERROR IS 80101; IF ( KMT_FH_FILE_DETAILS.ACCESS_2 (RESULT); RESULT LE 0 ) THEN @ Write successful @ BOOL TRACING IS KMT_TRACE_FLAGS.FH_TRACING; REF INT STATISTICS IS KMT_FH_FILE_STATISTICS.OUTPUT_TOTAL; STATISTICS := STATISTICS + 1; IF TRACING THEN () ( () KMT_MTM_VALUES PARAMS := DISPLAY( KMT_FH_RECORD_DETAILS.RECORD(SIZE KMT_FH_RECORD_DETAILS.RECORD_LENGTH) AS KMT_MTM_VALUES.RVB_VALUE); KMT_SP_LOG_TRACE_MESSAGE (KMT_FH_RECORD_OUT_MSG, PARAMS) ) FI; RESULT := 0 @ Ignore warnings @ ELSE () @ Write error @ ( () BYTE PROC_NAME := "KMT_FH_WRITE"; () BYTE ERROR_TEXT := " WHILST WRITING TO FILE"; () KMT_MTM_VALUES PARAMS := (PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE, ERROR_TEXT AS KMT_MTM_VALUES.RVB_VALUE); KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) FI END; @ KMT_FH_WRITE @ ***PAGE GLOBAL STATIC () PROC KMT_FH_SAVE_FILE IS ( RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to save the file previously opened by the procedure *@ @* KMT_FH_OPEN_FILE. *@ @* *@ @******************************************************************************@ BEGIN INT KMT_EH_SOFTWARE_ERROR IS 80101; IF KMT_FH_FILE_DETAILS.NEW_FILE AND ( CTM_SAVE_FILE (KMT_FH_FILE_DETAILS.FILE_CURRENCY, NIL, RESULT); RESULT GT 0 ) THEN () @ Save error @ ( () BYTE PROC_NAME := "KMT_FH_SAVE_FILE"; () KMT_MTM_VALUES PARAMS := DISPLAY(PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE); KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) ELSE @ Ignore warnings @ RESULT := 0 FI END; @ KMT_FH_SAVE_FILE @ ***PAGE GLOBAL STATIC () PROC KMT_FH_GIVE_NAME IS ( REF () BYTE NAME, REF INT NAME_LENGTH, BOOL FULL_NAME, RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to obtain either the full file name or the terminal *@ @* file name of the file previously opened by KMT_FH_OPEN_FILE. *@ @* The name of the file and length are returned in the areas referenced by *@ @* NAME and NAME_LENGTH respectively. *@ @* If FULL_NAME is set TRUE then the full file name will be returned, *@ @* otherwise the terminal file name will be returned. *@ @* If the area referenced by NAME is too small to contain the file name then *@ @* the file name will be truncated and resultcode FC_CTM_BUFFER_TOO_SHORT *@ @* returned. *@ @* *@ @******************************************************************************@ BEGIN INT KMT_EH_SOFTWARE_ERROR IS 80101; IF ( CTM_GIVE_NAME (KMT_FH_FILE_DETAILS.FILE_CURRENCY, NIL, NAME, NAME_LENGTH, RESULT); RESULT GT 0 ) THEN () @ Error @ ( () BYTE PROC_NAME := "KMT_FH_GIVE_NAME"; () KMT_MTM_VALUES PARAMS := DISPLAY(PROC_NAME AS KMT_MTM_VALUES.RVB_VALUE); KMT_EH_LOG_ERROR (RESULT, 2, PARAMS, 0, FALSE, FALSE); RESULT := KMT_EH_SOFTWARE_ERROR ) ELSF FULL_NAME THEN @ Full file name required @ @ Exit @ SKIP ELSF NAME_LENGTH EQ 0 THEN @ No file name returned, exit @ SKIP ELSE @ Terminal file name required @ () BYTE NAME_COPY := NAME(SIZE NAME_LENGTH); REF () BYTE TERMINAL_NAME, REM; TERMINAL_NAME := NAME_COPY; REM := TERMINAL_NAME; UNTIL @ Search for part of name @ SCANUNQ (".", @ after last dot @ REM, 0, REM) DO REM := REM(1::); TERMINAL_NAME := REM REPEAT; SCANUNQ ("(", @ Remove generation number @ TERMINAL_NAME, 0, REM); NAME_LENGTH := LENGTH TERMINAL_NAME - LENGTH REM; NAME(SIZE NAME_LENGTH) := TERMINAL_NAME(SIZE NAME_LENGTH); RESULT := 0 FI; END; @ KMT_FH_GIVE_NAME @ ENDMODULE @ KMT_FH_MODULE @ $$$$ KMT_MAIN_MODULE MODULE KMT_MAIN_MODULE; @ Version 1.01 @ @------------------------------------------------------------------------------@ @ @ @ @ @ ----- S W U R C C V M E K E R M I T ----- @ @ @ @ @ @ ---------------------------------------------------------------- @ @ @ @ @ @ Version 1.00 (February 1986) @ @ @ @ Written by : Richard Andrews and David Lord, @ @ South West Universities Regional Computer Centre, @ @ Claverton Down, Bath BA2 7AY, U.K. @ @ @ @ @ @ ---------------------------------------------------------------- @ @ @ @ @ @ Version 1.01 (October 1986) @ @ @ @ Fixes by : Dave Allum and David Lord, SWURCC. @ @ @ @ 1. The BOOL variable ASG_ROUTE is set by reading the BOOL ASG @ @ set in the interface procedure KERMIT. (If the BOOL ASG is @ @ not found ASG_ROUTE is set FALSE). ASG_ROUTE is used when @ @ checking valid characters for START-OF-PACKET etc. VME I/O @ @ cannot handle all control characters, the ASG can handle @ @ more than other communications controllers (eg NIC and CSC). @ @ @ @ 2. A warning message informs the user that VME KERMIT doesn't @ @ use the standard Kermit START-OF-PACKET character. @ @ @ @ 3. Attempts to set START-OF-PACKET, END-OF-LINE or PAD-CHARACTER @ @ to a character that cannot be handled by VME I/O are trapped. @ @ @ @ 4. VME KERMIT now does 8th bit prefixing correctly. @ @ @ @ 5. The EOF packet sent by VME KERMIT no longer contains the @ @ data field from the last Data packet sent. @ @ @ @ 6. The DELAY timer now works properly. Previously if the micro @ @ Kermit sent a Nak before the DELAY timer had expired a VME @ @ break-in occurred. @ @ @ @ 7. VME KERMIT in SERVER mode no longer sends the name of the @ @ first file sent in the File_Hdr packet for second (and @ @ subsequent) files requested via GET command on the remote @ @ Kermit. @ @ @ @ 8. VME KERMIT can now receive a batch of files sent by a micro @ @ Kermit using a wildcard send. Previously VME Kermit output @ @ several generations of the same filename. @ @ @ @ 9. The way VME KERMIT standardises filenames has been improved. @ @ (VME filenames don't conform to the form 'name.type' as @ @ in the Kermit protocol: see KMT_SP_STANDARDISE_FILENAME) @ @ @ @ 10. Resources are released after each transfer so that a file @ @ that has just been sent to VME can be accessed by other users. @ @ @ @ 11. The DEBUG information at PACKET level is now in a more @ @ readable form. @ @ @ @------------------------------------------------------------------------------@ @ Mode declarations: @ MODE KMT_BUFFER IS (96)BYTE; MODE KMT_STRING IS REF()BYTE; MODE KMT_WORD IS REF()BYTE; 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); MODE KMT_PP_PACKET_STATISTICS_S IS STRUCT (INT INPUT_TOTAL, OUTPUT_TOTAL); @ External procedures @ EXT PROC (RESPONSE) KMT_UI; EXT PROC (REF INT,INT,RESPONSE) KMT_PH; EXT PROC (REF INT,REF INT,RESPONSE) KMT_PP_GET_PACKET, PROC (INT,INT,BOOL,RESPONSE) KMT_PP_SEND_PACKET, PROC (REF()BYTE,RESPONSE) KMT_PP_BUILD_STRING_PACKET_DATA; EXT PROC (RESPONSE) KMT_DH_OPEN_FILE, PROC (RESPONSE) KMT_DH_CLOSE_FILE; EXT PROC (RESPONSE) KMT_EH_INFORM_PE_CONTINGENCY; EXT PROC (RESPONSE) KMT_FH_CLOSE_FILE, PROC (RESPONSE) KMT_FH_SAVE_FILE; EXT PROC (INT,REF()KMT_MTM_VALUES) INT KMT_SP_MTM; EXT PROC (REF KMT_STRING) KMT_WORD KMT_SP_GET_WORD; EXT PROC () KMT_SP_SET_DEFAULTS; EXT PROC (INT,REF()KMT_MTM_VALUES) KMT_SP_LOG_TRACE_MESSAGE; EXT () PROC () ENDJOB; EXT () PROC (WORD,WORD,REF()BYTE,RESPONSE) CTM_LOG; EXT () PROC (RESPONSE) CTM_JS_BEGIN; EXT () PROC (RESPONSE) CTM_JS_END; EXT () PROC (REF () BYTE,LONG WORD,REF () WORD,REF LONG LONG WORD,RESPONSE) CTM_JS_CALL; EXT () PROC (REF () BYTE,REF LONG INT,REF () BYTE,REF BOOL,RESPONSE) CTM_JS_READ; @ External constants: @ EXT INT UNSET,EXIT,LOGOUT,FATAL_ERROR; @ Miscellaneous constants @ EXT INT SERVER_MODE,COMMAND_MODE; EXT INT REC_SERVER_IDLE,REC_INIT,SEND_INIT,ENTRY,ABORT,COMPLETE; EXT INT ERROR_PKT; @ External variables @ EXT REF () BYTE KMT_VERSION; EXT REF BOOL ASG_ROUTE; EXT REF()KMT_MTM_VALUES KMT_MTM_AREA; EXT REF()BYTE MTM_TEXT; EXT REF INT MTM_TEXT_LEN; EXT REF ()REF ()BYTE MTM_RECALL_DATA; EXT REF INT RC_IGNORED; EXT REF INT PKT_SEQ,PKT_NO,PKT_TYPE; EXT REF BOOL SAVE_INCOMPLETE_FILE; EXT REF INT RETRY_COUNT,TIMEOUT_TOTAL; EXT REF INT EXIT_STATE,KMT_CURRENT_MODE,KMT_PH_STATE; EXT REF KMT_BUFFER KMT_VME_FILE_BUF,KMT_REM_FILE_BUF; EXT REF KMT_WORD KMT_VME_FILE,KMT_REM_FILE; GLOBAL STATIC PROC KMT_MESSAGE IS (INT MSG_NO,RESPONSE RESULT): @ outputs messages to terminal and journal file @ @ if error returned from protocol handler, an error packet is sent @ BEGIN INT REPLY := UNSET, M := IF MSG_NO > 0 THEN MSG_NO ELSE -MSG_NO @ warning message codes are negative @ FI; RESULT := 0; WHILE REPLY = UNSET DO @ expand message @ REPLY := KMT_SP_MTM(M,KMT_MTM_AREA); IF REPLY = -1 OR REPLY = 0 THEN CTM_LOG(3,6,MTM_TEXT(SIZE MTM_TEXT_LEN),RC_IGNORED); IF M = MSG_NO @ 1st message text from error number @ THEN @ protocol handler error, send 1st message in error pkt @ KMT_PP_BUILD_STRING_PACKET_DATA(MTM_TEXT(SIZE MTM_TEXT_LEN), RC_IGNORED); KMT_PP_SEND_PACKET(ERROR_PKT,PKT_SEQ,FALSE,RC_IGNORED); IF RC_IGNORED > 0 THEN @ fatal error sending packet! - continue expansion @ @ of current message, but ensure abort afterwards @ KMT_PH_STATE := ABORT; @ set abort state @ EXIT_STATE := FATAL_ERROR; RESULT := -89061 FI FI; IF REPLY = 0 AND RESULT NE 0 THEN @ error sending packet, record message @ M := -RESULT; RESULT := 0 @ zero result always returned @ ELSE M := REPLY @ continue message text expansion @ FI FI REPEAT END ; @ KMT_MESSAGE @ STATIC PROC KERMIT_SUPPORT IS (REF () BYTE OPTION,REF () BYTE VME_FILE, REF () BYTE REM_FILE,RESPONSE RESULT): BEGIN INT KMT_OPTION; @ mode supplied on entry to Kermit @ PROC VALIDATE_ARGS IS (RESPONSE RESULT): @ checks Kermit option and verifies that file arguments are @ @ present for Receive or Send options @ @ sets initial protocal handler state (where appropriate) @ BEGIN @ remove leading and trailing spaces from filenames @ ()BYTE VME_BUF := VME_FILE; KMT_WORD VME_PTR := VME_BUF; ()BYTE REM_BUF := REM_FILE; KMT_WORD REM_PTR := REM_BUF; KMT_VME_FILE := KMT_SP_GET_WORD(VME_PTR); KMT_REM_FILE := KMT_SP_GET_WORD(REM_PTR); KMT_MTM_AREA(3) := OPTION AS KMT_MTM_VALUES.RVB_VALUE; KMT_OPTION := KMT_CURRENT_MODE := KMT_SP_MTM(5000,KMT_MTM_AREA(SIZE 4)); @ validate option @ RESULT := 0; CASE KMT_OPTION THEN @ Server - no file args should be present @ KMT_PH_STATE := REC_SERVER_IDLE; UNLESS KMT_VME_FILE REF NIL AND KMT_REM_FILE REF NIL DO KMT_VME_FILE := NIL; KMT_REM_FILE := NIL; RESULT := -85000 @ warning @ FI ELSE @ Receive - VME_FILE may be present but not REM_FILE @ KMT_PH_STATE := REC_INIT; UNLESS KMT_VME_FILE REF NIL DO KMT_VME_FILE := KMT_VME_FILE_BUF(SIZE LENGTH KMT_VME_FILE) := KMT_VME_FILE FI; UNLESS KMT_REM_FILE REF NIL DO KMT_REM_FILE := NIL; RESULT := -85001 @ warning @ FI ELSE @ Send - VME_FILE must be present, REM_FILE is optional @ KMT_PH_STATE := SEND_INIT; IF KMT_VME_FILE REF NIL THEN EXIT_STATE := FATAL_ERROR; RESULT := -85010 @ error @ ELSE KMT_VME_FILE := KMT_VME_FILE_BUF(SIZE LENGTH VME_FILE):= KMT_VME_FILE; UNLESS KMT_REM_FILE REF NIL DO KMT_REM_FILE := KMT_REM_FILE_BUF(SIZE LENGTH KMT_REM_FILE) := KMT_REM_FILE FI FI ELSE @ Command - no file arguments should be present @ KMT_PH_STATE := UNSET; UNLESS KMT_VME_FILE REF NIL AND KMT_REM_FILE REF NIL DO KMT_VME_FILE := NIL; KMT_REM_FILE := NIL; RESULT := -85000 @ warning @ FI DEFAULT @ invalid entry mode @ EXIT_STATE := FATAL_ERROR; RESULT := -85020 ESAC END ; @ VALIDATE_ARGS @ PROC CLOSE_FILES IS (RESPONSE RESULT): @ close Kermit Send/Receive files when aborting @ BEGIN INT RC; KMT_FH_CLOSE_FILE(RC); RESULT := IF RC <= 0 THEN 0 @ ignore -ve warnings @ ELSE 89042 @ error closing file @ FI; IF SAVE_INCOMPLETE_FILE THEN KMT_FH_SAVE_FILE(RC); IF RC > 0 THEN RESULT := 89044 @ error saving file @ FI FI; KMT_VME_FILE := NIL; KMT_REM_FILE := NIL END ; @ CLOSE_FILES @ @ main Kermit segment @ EXIT_STATE := UNSET; KMT_SP_SET_DEFAULTS(); @ initialise message text area @ KMT_MTM_AREA(SIZE 3) := (MTM_TEXT AS KMT_MTM_VALUES.RVB_VALUE, MTM_TEXT_LEN AS KMT_MTM_VALUES.RI_VALUE, MTM_RECALL_DATA AS KMT_MTM_VALUES.RVRVB_VALUE); KMT_MTM_AREA(3 SIZE 2) := (1 AS KMT_MTM_VALUES.LI_VALUE, KMT_VERSION AS KMT_MTM_VALUES.RVB_VALUE); KMT_MESSAGE(-1,RC_IGNORED); @ output banners @ KMT_SP_LOG_TRACE_MESSAGE(2,NIL); VALIDATE_ARGS(RESULT); IF RESULT NE 0 THEN @ output message & continue (n.b. exit state may be fatal_error) @ KMT_MESSAGE(RESULT,RESULT) FI; KMT_DH_OPEN_FILE(RESULT); IF RESULT NE 0 THEN KMT_MESSAGE(RESULT,RESULT); EXIT_STATE := FATAL_ERROR FI; IF CTM_JS_BEGIN(RESULT); @ start new SCL block @ RESULT > 0 THEN EXIT_STATE := FATAL_ERROR FI; IF EXIT_STATE = UNSET THEN @ notify user of non-standard START-OF-PACKET @ KMT_MESSAGE(-3,RC_IGNORED) FI; WHILE EXIT_STATE = UNSET DO RESULT := 0; @ everything ok at this point @ IF KMT_CURRENT_MODE = COMMAND_MODE THEN @ get command from user, if command is SERVER, SEND or RECEIVE @ @ then KMT_CURRENT_MODE and KMT_PH_STATE will be reset @ KMT_UI(RESULT); IF RESULT NE 0 THEN KMT_MESSAGE(RESULT,RESULT) FI ELSE @ sending or receiving, carry out action on entry to protocol @ @ handler state, wait for a packet, then carry out action in @ @ response to type of packet received @ KMT_PH(KMT_PH_STATE,ENTRY,RESULT); IF RESULT = 0 THEN KMT_PP_GET_PACKET(PKT_TYPE,PKT_NO,RESULT); IF RESULT = 39854 @ timeout @ THEN TIMEOUT_TOTAL := TIMEOUT_TOTAL + 1; RESULT := 0 FI; IF RESULT <= 0 THEN @ warning message already ouput, continue @ RESULT := 0; KMT_PH(KMT_PH_STATE,PKT_TYPE,RESULT) FI FI; IF RESULT NE 0 THEN KMT_MESSAGE(RESULT,RESULT) FI; IF KMT_PH_STATE = ABORT THEN CLOSE_FILES(RESULT); IF RESULT NE 0 THEN KMT_MESSAGE(RESULT,RESULT) FI; KMT_PH_STATE := COMPLETE FI; IF KMT_PH_STATE = COMPLETE THEN IF CTM_JS_END(RESULT); @ close current SCL block @ RESULT > 0 THEN EXIT_STATE := FATAL_ERROR ELSF CTM_JS_BEGIN(RESULT); @ open new SCL block @ RESULT > 0 THEN EXIT_STATE := FATAL_ERROR ELSE PKT_SEQ := 0; @ zero packet sequence @ IF KMT_CURRENT_MODE = SERVER_MODE THEN @ remain in Server mode until EXIT_STATE is set @ @ (may already have been set by Server Generic command) @ KMT_PH_STATE := REC_SERVER_IDLE; RETRY_COUNT := 0 ELSF KMT_OPTION = COMMAND_MODE THEN @ resume Command mode on completion of Send/Receive @ KMT_CURRENT_MODE := COMMAND_MODE ELSE @ Send or Receive specified in VME command, exit on @ EXIT_STATE := EXIT @ completion @ FI FI FI FI REPEAT; CTM_JS_END(RC_IGNORED); @ close current SCL block @ KMT_DH_CLOSE_FILE(RC_IGNORED); @ close logging files @ IF EXIT_STATE = FATAL_ERROR THEN KMT_MESSAGE(-85030,RC_IGNORED) @ tell user @ ELSF EXIT_STATE = LOGOUT THEN @ log out Kermit after receiving Generic Logout command @ KMT_MESSAGE(-85031,RC_IGNORED); ENDJOB() ELSE KMT_MESSAGE(-85032,RC_IGNORED) @ output newline @ FI END ; @ KERMIT_SUPPORT @ GLOBAL STATIC () PROC KERMIT_THE_FROG IS (() REF()BYTE OPTION, () REF()BYTE VME_FILE, () REF()BYTE REM_FILE, () RESPONSE RESULT): BEGIN ()BYTE JSV_NAME := "ASG"; @ obtain value for ASG_ROUTE bool @ CTM_JS_READ(JSV_NAME,NIL,NIL,ASG_ROUTE,RC_IGNORED); IF RC_IGNORED NE 0 THEN ASG_ROUTE := FALSE FI; @ verify parameter references (parameter values validated later): @ @ OPTION must be of mode REF () BYTE, may not be ZLR or NIL @ @ VME_FILE must be of mode REF () BYTE, may be ZLR, must not be NIL @ @ REM_FILE must be of mode REF () BYTE, may be ZLR, must not be NIL @ UNLESS (VERIFY OPTION AND VALIDR OPTION) AND (VERIFY VME_FILE AND (VALIDR VME_FILE OR NOT(VME_FILE IS NIL))) AND (VERIFY REM_FILE AND (VALIDR REM_FILE OR NOT(REM_FILE IS NIL))) THEN @ invalid parameter reference @ RESULT := 10002 @ ARCH_INACCESSIBLE_PARAMETER @ ELSF @ create resource block @ CTM_JS_BEGIN(RESULT); RESULT <= 0 THEN @ resource block created @ LONG LONG WORD KERMIT_RESULT; ANY((3)LONG WORD AS_LW,(6) WORD AS_W) PARAMS; PARAMS.AS_LW := (BDESC OPTION,BDESC VME_FILE,BDESC REM_FILE); @ set up program error handler @ IF KMT_EH_INFORM_PE_CONTINGENCY(RESULT); RESULT > 0 THEN @ failed to set error handler @ SKIP ELSF CTM_JS_CALL(NIL,PDESC KERMIT_SUPPORT,PARAMS.AS_W,KERMIT_RESULT, RESULT); @ create firewall @ RESULT <= 0 THEN @ either exited normally or via CTM_STOP @ RESULT := IF (S'S'KERMIT_RESULT) <= 0 THEN 0 @ ignore warnings @ ELSE 52000 @ error return common resultcode @ FI FI; CTM_JS_END(RC_IGNORED) @ end resource block @ FI END ; @ KERMIT_THE_FROG @ ENDMODULE @ KMT_MAIN_MODULE @ $$$$ KMT_PH_MODULE MODULE KMT_PH_MODULE; @ VME KERMIT PROTOCOL HANDLER @ @ GLOBAL VARIABLES @ @ PKT_TYPE : packet type of current packet @ @ KMT_PH_INPUT_PACKET_DATA : pointer to packet data buffer @ @ (translated to EBCDIC and decoded) @ @ PKT_SEQ : current packet number (expected) @ @ PKT_NO : current packet number (received) @ @ RETRY_COUNT : current retry count @ @ Mode declarations: @ MODE KMT_BUFFER IS (96)BYTE; MODE KMT_STRING IS REF()BYTE; MODE KMT_WORD IS REF()BYTE; MODE KMT_MTUP_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); MODE KMT_PP_PACKET_STATISTICS_S IS STRUCT (INT INPUT_TOTAL, OUTPUT_TOTAL); MODE KMT_TRACE_FLAGS_S IS WORD STRUCT (BIT PH_TRACING, PP_TRACING, FH_TRACING, DH_TRACING, 28-BIT SPARE); @ External procedures @ EXT PROC (INT,RESPONSE) KMT_MESSAGE; EXT PROC (RESPONSE) KMT_UI; EXT PROC (REF()BYTE,INT,RESPONSE) KMT_FH_OPEN_FILE, PROC (RESPONSE) KMT_FH_CLOSE_FILE, PROC (RESPONSE) KMT_FH_SAVE_FILE, PROC (REF()BYTE,REF INT,BOOL,RESPONSE) KMT_FH_GIVE_NAME; EXT PROC () KMT_PP_TRANSLATE_TO_EBCDIC, PROC (REF()BYTE,RESPONSE) KMT_PP_BUILD_STRING_PACKET_DATA, PROC (RESPONSE) KMT_PP_PROCESS_PARAM_PACKET_DATA, PROC () KMT_PP_BUILD_PARAM_PACKET_DATA, PROC (RESPONSE) KMT_PP_BUILD_FILE_RECORD, PROC (RESPONSE) KMT_PP_BUILD_FILE_PACKET_DATA, PROC (REF INT,REF INT,RESPONSE) KMT_PP_GET_PACKET, PROC (INT,INT,BOOL,RESPONSE) KMT_PP_SEND_PACKET; @ Any error returned by KMT_PP_SEND_PACKET is fatal and Kermit will exit; @ @ warnings will have been logged already and are ignored @ EXT PROC (REF KMT_STRING) KMT_WORD KMT_SP_GET_WORD, PROC (REF KMT_WORD,INT) KMT_SP_STANDARDISE_FILENAME, PROC (INT,REF()KMT_MTUP_VALUES) KMT_SP_LOG_TRACE_MESSAGE; EXT REF INT PKT_SEQ,PKT_NO,MAXTRY,RETRY_COUNT,RETRY_TOTAL,TIMEOUT_TOTAL, RC_IGNORED; EXT REF KMT_STRING KMT_PH_INPUT_PACKET_DATA; EXT REF KMT_BUFFER KMT_VME_FILE_BUF,KMT_REM_FILE_BUF; EXT REF KMT_WORD KMT_VME_FILE,KMT_REM_FILE; EXT INT ENTRY,BREAK_PKT,DATA_PKT,FILE_HDR_PKT,NAK_PKT,SEND_INIT_PKT,ACK_PKT, EOF_PKT; EXT INT VME_TERM,VME_STD,KMT_STD; @ forms of name standardisation @ EXT INT REC_SERVER_IDLE,REC_INIT,REC_FILE,REC_DATA,SEND_INIT,SEND_FILE, SEND_DATA,SEND_EOF,SEND_BREAK,COMPLETE,ABORT; EXT INT EXIT,LOGOUT,FATAL_ERROR; @ exit states @ EXT INT EOF; @ eof on file data @ EXT INT SERVER_MODE; EXT REF INT KMT_CURRENT_MODE; EXT BOOL READ_INT,NO_READ_INT; @ set/don't set read interest after send @ EXT REF INT FILE_OPTION; EXT REF BOOL DELAY_TIMER; EXT REF BOOL SAVE_INCOMPLETE_FILE; EXT REF INT EXIT_STATE; EXT REF()KMT_MTUP_VALUES KMT_MTM_AREA; EXT REF KMT_PP_PACKET_STATISTICS_S KMT_PP_PACKET_STATISTICS; EXT REF KMT_TRACE_FLAGS_S KMT_TRACE_FLAGS; STATIC REF KMT_STRING PKT_DATA IS KMT_PH_INPUT_PACKET_DATA; GLOBAL STATIC () PROC KMT_PH IS (REF INT STATE,INT EVENT,RESPONSE RESULT): BEGIN @ procedures for state entry @ SIM PROC KMT_PH_REC_SERVER_IDLE IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Server idle, waiting for message @ BEGIN RETRY_COUNT := 0; @ try for ever in Rec_Server_Idle state @ RETRY_TOTAL := TIMEOUT_TOTAL := 0; KMT_PP_PACKET_STATISTICS := (0,0); PKT_SEQ := 0; @ initialise packet sequence @ RESULT := 0 END ; @ KMT_PH_REC_SERVER_IDLE @ SIM PROC KMT_PH_REC_INIT IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Entry point for non-server RECEIVE command @ BEGIN PKT_SEQ := 0; @ initialise packet sequence @ RESULT := 0 END ; @ KMT_PH_REC_INIT @ SIM PROC KMT_PH_REC_FILE IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Look for a file header or EOT message @ RESULT := 0 @ nothing to do on entry to Rec_File state @ ; @ KMT_PH_REC_FILE @ SIM PROC KMT_PH_REC_DATA IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Receive data up to end of file @ RESULT := 0 @ nothing to do on entry to Rec_Data state @ ; @ KMT_PH_REC_DATA @ SIM PROC KMT_PH_SEND_INIT IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Server Send Init, also entry for non-server SEND command @ BEGIN PKT_SEQ := 0; @ initialise packet sequence @ IF KMT_CURRENT_MODE NE SERVER_MODE AND RETRY_COUNT LE 1 THEN @ wait for user to set up remote KERMIT @ INT KMT_EH_SOFTWARE_ERROR IS 80101; INT X_TYPE,X_NO; DELAY_TIMER := TRUE; @ set delay timer @ KMT_PP_GET_PACKET(X_TYPE,X_NO,RESULT);@ attempt to read packet @ @ if we get a packet then they're ready to receive @ @ if the timer expires then we send regardless @ DELAY_TIMER := FALSE; UNLESS RESULT = KMT_EH_SOFTWARE_ERROR DO RESULT := 0 FI ELSE RESULT := 0 FI; IF RESULT = 0 THEN KMT_PP_BUILD_PARAM_PACKET_DATA(); @ send S(0) with parameters @ KMT_PP_SEND_PACKET(SEND_INIT_PKT,PKT_SEQ,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI FI END ; @ KMT_PH_SEND_INIT @ SIM PROC KMT_PH_SEND_FILE IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Send file or text header (we don't send text packets!) @ BEGIN @ send F(n) - packet made by KMT_PH_READY_FILE @ KMT_PP_SEND_PACKET(FILE_HDR_PKT,PKT_SEQ,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI END ; @ KMT_PH_SEND_FILE @ SIM PROC KMT_PH_SEND_DATA IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Send contents of file or textual information @ @ (we don't send text packets!) @ BEGIN @ send D(n) with current buffer (pkt made by KMT_PH_READY_DATA) @ KMT_PP_SEND_PACKET(DATA_PKT,PKT_SEQ,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI END ; @ KMT_PH_SEND_DATA @ SIM PROC KMT_PH_SEND_EOF IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Send end of file indicator (we don't do interrupts) @ BEGIN KMT_VME_FILE := NIL; @ file has been closed @ KMT_REM_FILE := NIL; @ send Z(n) - packet made by KMT_PH_READY_DATA @ KMT_PP_SEND_PACKET(EOF_PKT,PKT_SEQ,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI END ; @ KMT_PH_SEND_EOF @ SIM PROC KMT_PH_SEND_BREAK IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ End of Transmission @ BEGIN @ send B(n) - packet made by KMT_PH_SENT_FILE @ KMT_PP_SEND_PACKET(BREAK_PKT,PKT_SEQ,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI END ; @ KMT_PH_SEND_BREAK @ @ procedures for expected packets @ SIM PROC KMT_PH_INIT_PARAMS IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ A Send_Init or Init packet has arrived. If the packet sequence is @ @ correct, process their parameters and ack with our parameters. @ @ If it's a repeat of their last packet, ack it again with our @ @ parameters. Otherwise, report error and in non-Server modes, abort @ IF (STATE = REC_SERVER_IDLE OR STATE = REC_INIT) AND PKT_NO = 0 THEN @ got right packet, reset retry count @ RETRY_COUNT := 0; KMT_PP_PROCESS_PARAM_PACKET_DATA(RESULT); IF RESULT = 0 THEN KMT_PP_BUILD_PARAM_PACKET_DATA(); KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI; IF RESULT = 0 AND EVENT = SEND_INIT_PKT THEN @ increment packet sequence @ PKT_SEQ := PKT_SEQ+1 MOD 64; STATE := REC_FILE FI ELSE @ their params unacceptable @ RESULT := 89070 FI ELSF STATE = REC_FILE AND PKT_NO+1 MOD 64 = PKT_SEQ @ i.e. P = N-1 @ THEN @ we've picked up their Send_init again, so send ack @ KMT_PP_BUILD_PARAM_PACKET_DATA(); KMT_PP_SEND_PACKET(ACK_PKT,PKT_NO,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI ELSE @ wrong packet sequence, error (abort if non-server) @ RESULT := 89000 FI ; @ KMT_PH_INIT_PARAMS @ SIM PROC KMT_PH_GEN_CMD IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Generic command received - some are implemented and will be @ @ executed and acknowledged - an error packet is sent for the rest @ IF PKT_NO = 0 THEN BYTE GEN_CMD; KMT_PP_TRANSLATE_TO_EBCDIC(); GEN_CMD := PKT_DATA(0); RETRY_COUNT := 0; @ got right packet, reset retry count @ @ check if Generic Command implemented @ IF GEN_CMD = "F" OR GEN_CMD = "L" THEN @ GF (Finish command): exit Server mode and terminate @ @ GL (Logout command): exit Server mode and log out @ EXIT_STATE := IF GEN_CMD = "F" THEN EXIT ELSE LOGOUT FI; STATE := COMPLETE; @ Generic Command successful, ack it @ KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI ELSE @ this Generic Command not implemented (or doesn't exist) @ RESULT := 89011 FI ELSE @ wrong packet number, wait for their next try @ RESULT := 89000 FI ; @ KMT_PH_GEN_CMD @ SIM PROC KMT_PH_KMT_CMD IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Packet contains Kermit command, pass it to user interface (KMT_UI) @ @ for processing @ IF PKT_NO = 0 THEN RETRY_COUNT := 0; @ got right packet, reset retry count @ @ pass command (in packet) to KMT_UI @ KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); KMT_PP_TRANSLATE_TO_EBCDIC(); KMT_UI(RESULT); IF RESULT = 0 THEN @ command has been executed successfully so ack it @ @ if there is a reply, KMT_UI has put it into packet @ KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI FI ELSE @ wrong packet number, wait for their next try @ RESULT := 89000 FI ; @ KMT_PH_KMT_CMD @ SIM PROC KMT_PH_GOT_FILENAME IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Packet contains name of file to be sent @ IF PKT_NO = 0 THEN @ got right packet, reset retry count @ RETRY_COUNT := 0; KMT_PP_TRANSLATE_TO_EBCDIC(); KMT_VME_FILE := KMT_SP_GET_WORD(PKT_DATA); @ obtain filename @ IF NOT (KMT_VME_FILE REF NIL) @ must be present @ THEN KMT_VME_FILE := KMT_VME_FILE_BUF(SIZE LENGTH KMT_VME_FILE) := KMT_VME_FILE; STATE := SEND_INIT; RESULT := 0 ELSE @ no filename, error and abort @ RESULT := 89030 FI ELSE @ wrong packet number, wait for their next try @ RESULT := 89000 FI ; @ KMT_PH_GOT_FILENAME @ SIM PROC KMT_PH_BREAK IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ End of Transmission received @ IF PKT_NO = PKT_SEQ THEN @ correct sequence, ack it and complete @ KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,NO_READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI; STATE := COMPLETE ELSE @ wrong packet sequence, error abort @ RESULT := 89000 FI ; @ KMT_PH_BREAK @ SIM PROC KMT_PH_FILE_HDR IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Packet contains name of file to be received @ IF PKT_NO = PKT_SEQ THEN @ obtain filename (may have been specified in Receive command)@ KMT_PP_TRANSLATE_TO_EBCDIC(); IF KMT_VME_FILE REF NIL THEN @ not already set @ KMT_VME_FILE := KMT_SP_GET_WORD(PKT_DATA); IF KMT_VME_FILE REF NIL THEN RESULT := 80931 ELSE KMT_VME_FILE := KMT_VME_FILE_BUF(SIZE LENGTH KMT_VME_FILE) := KMT_VME_FILE; RESULT := 0 FI ELSE @ already set but verify packet contains filename @ KMT_REM_FILE := KMT_SP_GET_WORD(PKT_DATA); RESULT := IF KMT_REM_FILE REF NIL THEN 80931 ELSE 0 FI FI; IF RESULT = 0 THEN @ open file @ KMT_REM_FILE := @ save copy of VME filename @ KMT_REM_FILE_BUF(SIZE LENGTH KMT_VME_FILE) := KMT_VME_FILE; @ assume filename is name.type, remove type @ KMT_SP_STANDARDISE_FILENAME(KMT_VME_FILE,VME_STD); KMT_FH_OPEN_FILE(KMT_VME_FILE,FILE_OPTION,RESULT); IF RESULT <= 0 THEN @ file open, log full name @ INT NAME_LENGTH; RESULT := 0; KMT_FH_GIVE_NAME(KMT_VME_FILE_BUF,NAME_LENGTH,TRUE,RESULT); IF RESULT <= 0 THEN @ set VME filename to full name @ RESULT := 0; KMT_VME_FILE := KMT_VME_FILE_BUF(SIZE NAME_LENGTH); KMT_MTM_AREA(3) := KMT_REM_FILE AS KMT_MTUP_VALUES.RVB_VALUE; KMT_MTM_AREA(4) := KMT_VME_FILE AS KMT_MTUP_VALUES.RVB_VALUE; KMT_MESSAGE(-87002,RC_IGNORED); @ log filename @ @ ack file header including VME filename @ KMT_PP_BUILD_STRING_PACKET_DATA(KMT_VME_FILE, RC_IGNORED); KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT); IF RESULT <= 0 THEN PKT_SEQ := PKT_SEQ+1 MOD 64; RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1); RETRY_COUNT := 0; STATE := REC_DATA; RESULT := 0 ELSE RESULT := -89061 FI FI ELSE @ unable to open file, reset result and abort @ RESULT := 89040 FI FI ELSE @ wrong packet number, abort @ RESULT := 89000 FI ; @ KMT_PH_FILE_HDR @ SIM PROC KMT_PH_GOT_DATA IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Received data packet @ IF PKT_NO = PKT_SEQ THEN @ write data to file @ KMT_PP_BUILD_FILE_RECORD(RESULT); IF RESULT <= 0 THEN @ ack data packet @ RESULT := 0; KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT); IF RESULT <= 0 THEN PKT_SEQ := PKT_SEQ+1 MOD 64; RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1); RETRY_COUNT := 0; RESULT := 0 ELSE RESULT := -89061 FI ELSE @ error writing data to file, abort @ RESULT := 89046 FI ELSF PKT_NO+1 MOD 64 = PKT_SEQ @ i.e. P = N-1 @ THEN @ we've picked up their last data packet again, so ack it @ KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); KMT_PP_SEND_PACKET(ACK_PKT,PKT_NO,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI ELSE @ wrong packet number, error abort @ RESULT := 89000 FI ; @ KMT_PH_GOT_DATA @ SIM PROC KMT_PH_GOT_FILE IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ End of file packet received @ IF PKT_NO = PKT_SEQ THEN KMT_PP_TRANSLATE_TO_EBCDIC(); KMT_FH_CLOSE_FILE(RESULT); @ close file we've just rec'd @ RESULT := IF RESULT <= 0 THEN 0 @ ignore -ve warning code @ ELSE 89042 @ error closing file, abort @ FI; IF (RESULT = 0 OR SAVE_INCOMPLETE_FILE) AND (LENGTH PKT_DATA = 0 OR PKT_DATA(0) NE "D") THEN @ no discard signal in packet so save file @ INT RC; KMT_FH_SAVE_FILE(RC); IF RC > 0 THEN RESULT := 89044 @ error saving file, abort @ FI FI; IF RESULT = 0 THEN KMT_VME_FILE := NIL; KMT_REM_FILE := NIL; @ no problems closing file, so ack eof @ KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT); IF RESULT <= 0 THEN PKT_SEQ := PKT_SEQ+1 MOD 64; RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1); RETRY_COUNT := 0; STATE := REC_FILE; RESULT := 0 ELSE RESULT := -89061 FI FI ELSE @ wrong packet number, abort @ RESULT := 89000 FI ; @ KMT_PH_GOT_FILE @ SIM PROC KMT_PH_READY_FILE IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Send Init has been acknowledged, open file for transfer @ IF PKT_NO = 0 THEN KMT_PP_PROCESS_PARAM_PACKET_DATA(RESULT); IF RESULT = 0 THEN @ open file in READ mode @ @ assume filename is name.type, remove type @ KMT_SP_STANDARDISE_FILENAME(KMT_VME_FILE,VME_STD); KMT_FH_OPEN_FILE(KMT_VME_FILE,0,RESULT); IF RESULT <= 0 THEN @ set up filename for file hdr packet @ INT NAME_LENGTH; RESULT := 0; KMT_FH_GIVE_NAME(KMT_VME_FILE_BUF,NAME_LENGTH,TRUE,RESULT); IF RESULT <= 0 THEN KMT_VME_FILE := KMT_VME_FILE_BUF(SIZE NAME_LENGTH); IF KMT_REM_FILE REF NIL THEN @ set remote filename to VME terminal name @ KMT_REM_FILE := KMT_REM_FILE_BUF(SIZE NAME_LENGTH) := KMT_VME_FILE; KMT_SP_STANDARDISE_FILENAME(KMT_REM_FILE,VME_TERM) ELSE @ set remote filename to Kermit Normal-Form @ KMT_SP_STANDARDISE_FILENAME(KMT_REM_FILE,KMT_STD) FI; @ log filenames @ KMT_MTM_AREA(3) := KMT_VME_FILE AS KMT_MTUP_VALUES.RVB_VALUE; KMT_MTM_AREA(4) := KMT_REM_FILE AS KMT_MTUP_VALUES.RVB_VALUE; KMT_MESSAGE(-87003,RC_IGNORED); @ put filename in file header packet @ KMT_PP_BUILD_STRING_PACKET_DATA(KMT_REM_FILE,RC_IGNORED); PKT_SEQ := PKT_SEQ+1 MOD 64; RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1); RETRY_COUNT := 0; STATE := SEND_FILE; RESULT := 0 FI ELSE @ unable to open file, reset result and abort @ RESULT := 89041 FI ELSE @ their params unacceptable @ RESULT := 89070 FI FI ; @ KMT_PH_READY_FILE @ SIM PROC KMT_PH_READY_DATA IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Get data ready for transfer @ IF (EVENT = ACK_PKT AND PKT_NO = PKT_SEQ) OR (EVENT = NAK_PKT AND PKT_NO = PKT_SEQ+1 MOD 64) THEN PKT_SEQ := PKT_SEQ+1 MOD 64; RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1); RETRY_COUNT := 0; KMT_PP_TRANSLATE_TO_EBCDIC(); IF (LENGTH PKT_DATA = 1 AND STATE = SEND_DATA) AND (PKT_DATA(0) = "X" OR PKT_DATA(0) = "Z") THEN @ their ack packet requested interrupt transfer @ KMT_FH_CLOSE_FILE(RESULT); @ closing file shouldn't fail @ RESULT := IF RESULT <= 0 THEN 0 ELSE 89043 FI; KMT_MESSAGE(-87000,RC_IGNORED); @ log cancellation of xfer @ @ set up eof packet data @ KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); STATE := SEND_EOF ELSE @ check for ack of file header, it may have filename @ IF STATE = SEND_FILE @ used by remote Kermit, if so log it @ THEN STATE := SEND_DATA; KMT_MTM_AREA(3) := KMT_VME_FILE AS KMT_MTUP_VALUES.RVB_VALUE; IF LENGTH PKT_DATA > 0 THEN KMT_MTM_AREA(4) := PKT_DATA AS KMT_MTUP_VALUES.RVB_VALUE ELSE KMT_MTM_AREA(4) := KMT_REM_FILE AS KMT_MTUP_VALUES.RVB_VALUE FI; KMT_MESSAGE(-87001,RC_IGNORED) FI; @ set up next data packet @ KMT_PP_BUILD_FILE_PACKET_DATA(RESULT); IF RESULT = EOF THEN @ all data sent, close file and send eof next @ KMT_FH_CLOSE_FILE(RESULT); @ shouldn't fail @ RESULT := IF RESULT <= 0 THEN 0 ELSE 89043 FI; STATE := SEND_EOF @ all data sent @ ELSE @ error reading from file? @ RESULT := IF RESULT <= 0 THEN 0 ELSE 89047 FI FI FI ELSE RESULT := 0 FI ; @ KMT_PH_MAKE_DATA @ SIM PROC KMT_PH_SENT_FILE IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ File sent, check ack @ BEGIN IF (EVENT = ACK_PKT AND PKT_NO = PKT_SEQ) OR (EVENT = NAK_PKT AND PKT_NO = PKT_SEQ+1 MOD 64) THEN @ any more files? no - we only allow 1 per send so: @ PKT_SEQ := PKT_SEQ+1 MOD 64; RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1); RETRY_COUNT := 0; KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); @ set up break @ STATE := SEND_BREAK @ packet data @ @ (ditto if previous pkt_data(0) was "Z") @ FI; RESULT := 0 END ; @ KMT_PH_SENT_FILE @ SIM PROC KMT_PH_SEND_DONE IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Break sent, check ack @ BEGIN IF EVENT = ACK_PKT THEN IF PKT_NO = PKT_SEQ THEN STATE := COMPLETE FI ELSF PKT_NO = PKT_SEQ+1 MOD 64 OR PKT_NO = 0 THEN @ they've sent nak(n+1) or nak(0) @ STATE := COMPLETE FI; RESULT := 0 END ; @ KMT_PH_SEND_DONE @ @ procedures for unexpected packets @ SIM PROC KMT_PH_REPORT_ERR IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ unexpected pkt type, send error pkt and remain in same state @ RESULT := 89000 ; @ KMT_PH_REPORT_ERR @ SIM PROC KMT_PH_GOT_ERROR IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ they've reported an error to us, log error message and abort @ BEGIN @ decode packet data and set up message text area for logging @ KMT_PP_TRANSLATE_TO_EBCDIC(); KMT_MTM_AREA(3) := PKT_DATA AS KMT_MTUP_VALUES.RVB_VALUE; RESULT := -87010 END ; @ KMT_PH_GOT_ERROR @ SIM PROC KMT_PH_SEND_NAK IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ send nak packet @ BEGIN KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); KMT_PP_SEND_PACKET(NAK_PKT,PKT_SEQ,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI END ; @ KMT_PH_SEND_NAK @ SIM PROC KMT_PH_NAK_ABORT IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Send NAK and abort @ BEGIN KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); KMT_PP_SEND_PACKET(NAK_PKT,PKT_SEQ,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI; STATE := ABORT END ; @ KMT_PH_NAK_ABORT @ SIM PROC KMT_PH_ACK_LAST IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ if current packet is repeat of last packet then send ack @ IF PKT_NO+1 MOD 64 = PKT_SEQ @ i.e. P = N-1 @ THEN KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); KMT_PP_SEND_PACKET(ACK_PKT,PKT_NO,READ_INT,RESULT); RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI ELSE @ wrong packet sequence, error abort @ RESULT := 89000 FI ; @ KMT_PH_ACK_LAST @ SIM PROC KMT_PH_ERR_ABORT IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Send error packet and abort @ RESULT := 89001 ; @ KMT_PH_ERR_ABORT @ SIM PROC KMT_PH_SEND_IDLE IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ the wrong type of packet (or a bad packet) has arrived while @ @ sending a file - in this case it doesn't matter @ RESULT := 0 ; @ KMT_PH_SEND_IDLE @ SIM PROC KMT_PH_SET_ABORT IS GROUP KMT_PH_GRP (RESPONSE RESULT): @ Set ABORT state @ BEGIN STATE := ABORT; RESULT := 0 END ; @ KMT_PH_SET_ABORT @ @ protocol handler state event table @ (9)(15)SIM PROC GROUP KMT_PH_GRP(RESPONSE) KMT_PH_ACTION IS ((KMT_PH_REC_SERVER_IDLE , KMT_PH_REPORT_ERR , KMT_PH_REPORT_ERR , KMT_PH_GOT_ERROR , KMT_PH_REPORT_ERR , KMT_PH_GEN_CMD , KMT_PH_INIT_PARAMS , KMT_PH_KMT_CMD , KMT_PH_REPORT_ERR , KMT_PH_GOT_FILENAME , KMT_PH_INIT_PARAMS , KMT_PH_REPORT_ERR , KMT_PH_REPORT_ERR , KMT_PH_SEND_NAK , KMT_PH_REPORT_ERR), (KMT_PH_REC_INIT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_GOT_ERROR , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_INIT_PARAMS , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_SEND_NAK , KMT_PH_NAK_ABORT ), (KMT_PH_REC_FILE , KMT_PH_BREAK , KMT_PH_NAK_ABORT , KMT_PH_GOT_ERROR , KMT_PH_FILE_HDR , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_INIT_PARAMS , KMT_PH_NAK_ABORT , KMT_PH_ACK_LAST , KMT_PH_SEND_NAK , KMT_PH_NAK_ABORT ), (KMT_PH_REC_DATA , KMT_PH_ERR_ABORT , KMT_PH_GOT_DATA , KMT_PH_GOT_ERROR , KMT_PH_ACK_LAST , KMT_PH_ERR_ABORT , KMT_PH_ERR_ABORT , KMT_PH_ERR_ABORT , KMT_PH_ERR_ABORT , KMT_PH_ERR_ABORT , KMT_PH_ERR_ABORT , KMT_PH_ERR_ABORT , KMT_PH_GOT_FILE , KMT_PH_SEND_NAK , KMT_PH_ERR_ABORT ), (KMT_PH_SEND_INIT , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_GOT_ERROR , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_READY_FILE , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE ), (KMT_PH_SEND_FILE , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_GOT_ERROR , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_READY_DATA , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_READY_DATA , KMT_PH_SET_ABORT , KMT_PH_SEND_IDLE , KMT_PH_SET_ABORT ), (KMT_PH_SEND_DATA , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_GOT_ERROR , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_READY_DATA , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_READY_DATA , KMT_PH_SET_ABORT , KMT_PH_SEND_IDLE , KMT_PH_SET_ABORT ), (KMT_PH_SEND_EOF , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_GOT_ERROR , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SENT_FILE , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SENT_FILE , KMT_PH_SET_ABORT , KMT_PH_SEND_IDLE , KMT_PH_SET_ABORT ), (KMT_PH_SEND_BREAK , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_GOT_ERROR , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SEND_DONE , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SEND_DONE , KMT_PH_SET_ABORT , KMT_PH_SEND_IDLE , KMT_PH_SET_ABORT )); @ PROTOCOL HANDLER @ IF KMT_TRACE_FLAGS.PH_TRACING THEN () KMT_MTUP_VALUES PARAMS := (STATE AS KMT_MTUP_VALUES.RI_VALUE, (L'EVENT) AS KMT_MTUP_VALUES.LI_VALUE); KMT_SP_LOG_TRACE_MESSAGE(300,PARAMS) FI; IF EVENT = ENTRY THEN @ increment retry count and test against maximum @ RETRY_COUNT := RETRY_COUNT+1; IF RETRY_COUNT > MAXTRY THEN RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1); RESULT := 89050 ELSE KMT_PH_ACTION(STATE,EVENT)(RESULT) FI ELSE KMT_PH_ACTION(STATE,EVENT)(RESULT) FI; IF RESULT NE 0 THEN IF RESULT = -89061 THEN @ unable to send packet - fatal error @ STATE := ABORT; EXIT_STATE := FATAL_ERROR ELSF (RESULT NE 89000) OR (STATE NE REC_SERVER_IDLE) THEN @ abort unless wrong seq no in Rec_Server_Idle state @ STATE := ABORT FI FI END ; @ KMT_PH @ ENDMODULE @ KMT_PH_MODULE @ $$$$ KMT_PP_MODULE 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 () REF KMT_TRACE_FLAGS_S KMT_TRACE_FLAGS; EXT () REF KMT_FH_RECORD_DETAILS_S KMT_FH_RECORD_DETAILS; EXT () REF KMT_DH_DEVICE_DETAILS_S KMT_DH_DEVICE_DETAILS; EXT () REF KMT_PP_CONFG_PARAMS_S KMT_PP_LOCAL_CONFG_PARAMS; EXT () REF KMT_PP_CONFG_PARAMS_S KMT_PP_REMOTE_CONFG_PARAMS; EXT () REF KMT_PP_PACKET_STATISTICS_S KMT_PP_PACKET_STATISTICS; EXT () 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 () 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 () ( 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 () 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 () ( 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 () 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 () ( 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 () 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 () ( 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 () 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 () ( 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 () 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 () ( 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 () 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 () ( () 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 () 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 () ( () 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 @ $$$$ KMT_SP_MODULE MODULE KMT_SP_MODULE; @******************************************************************************@ @* *@ @* Mode definitions *@ @* *@ @******************************************************************************@ 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_FH_RECORD_DETAILS_S IS STRUCT ( BOOL FILE_OPEN, NEW_RECORD, END_OF_FILE, WORD TEXT_TYPE, @ 0 = EBCDIC @ @ 1 = IA5 @ @ 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_FH_FILE_STATISTICS_S IS STRUCT ( INT INPUT_TOTAL, INT OUTPUT_TOTAL); 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_TRACE_FLAGS_S IS WORD STRUCT ( BIT PH_TRACING, PP_TRACING, FH_TRACING, DH_TRACING, 28-BIT SPARE); 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); MODE KMT_BUFFER IS (96) BYTE; MODE KMT_STRING IS REF () BYTE; MODE KMT_WORD IS REF () BYTE; ***PAGE @******************************************************************************@ @* *@ @* External procedure references *@ @* *@ @******************************************************************************@ EXT () PROC (RESPONSE @ RESPONSE @ ) CTM_JS_BEGIN; EXT () PROC (RESPONSE @ RESPONSE @ ) CTM_JS_END; EXT () PROC (REF () BYTE, @ PROMPT @ REF () BYTE, @ MESSAGE @ REF LONG INT, @ LENGTH_MESSAGE @ RESPONSE @ RESPONSE @ ) ASK_MESSAGE; EXT () PROC (WORD, @ TYPE @ WORD, @ DESTINATION @ REF () BYTE, @ MESSAGE @ RESPONSE @ RESPONSE @ ) CTM_LOG; EXT () PROC (REF () REF () BYTE, @ NAMES @ REF () BYTE, @ JOURNAL_LIST @ RESPONSE @ RESPONSE @ ) SET_OPTIONS; EXT PROC (INT, @ TEXT_NUMBER @ REF () KMT_MTM_VALUES @ PARAMS @ ) INT KMT_SP_MTM; ***PAGE @******************************************************************************@ @* *@ @* External data references *@ @* *@ @******************************************************************************@ @ Constants: @ @ ********** @ EXT INT UNSET; EXT INT VME_TERM, @ 0 @ @forms of name standardisation @ VME_STD, @ 1 @ KMT_STD; @ 2 @ ***LINES(4) @ Variables: @ @ ********** @ EXT () REF BOOL TRANSLATE_FILENAME; EXT REF INT EXIT_STATE, FILE_OPTION, MAXTRY, RETRY_COUNT, RETRY_TOTAL, TIMEOUT_TOTAL; EXT REF WORD DELAY; EXT REF BOOL ASG_ROUTE, DELAY_TIMER, SAVE_INCOMPLETE_FILE; EXT () REF KMT_DH_DEVICE_DETAILS_S KMT_DH_DEVICE_DETAILS; EXT () REF KMT_FH_RECORD_DETAILS_S KMT_FH_RECORD_DETAILS; EXT () REF KMT_FH_FILE_STATISTICS_S KMT_FH_FILE_STATISTICS; EXT () REF KMT_PP_CONFG_PARAMS_S KMT_PP_LOCAL_CONFG_PARAMS; EXT () REF KMT_PP_CONFG_PARAMS_S KMT_PP_REMOTE_CONFG_PARAMS; EXT () REF KMT_PP_PACKET_STATISTICS_S KMT_PP_PACKET_STATISTICS; EXT () REF KMT_TRACE_FLAGS_S KMT_TRACE_FLAGS; ***LINES(4) @ Results: @ @ ******** @ ***PAGE @******************************************************************************@ @* *@ @* Procedure declarations *@ @* *@ @******************************************************************************@ GLOBAL STATIC () PROC KMT_SP_SET_DEFAULTS IS (): @******************************************************************************@ @* *@ @* This procedure is used to set default values for certain global variables. *@ @* *@ @******************************************************************************@ BEGIN EXIT_STATE := UNSET; FILE_OPTION := 1; @ create mode @ DELAY := 30; DELAY_TIMER := FALSE; SAVE_INCOMPLETE_FILE := FALSE; TRANSLATE_FILENAME := TRUE; MAXTRY := 5; RETRY_COUNT := 0; RETRY_TOTAL := 0; TIMEOUT_TOTAL := 0; KMT_TRACE_FLAGS := 0; @ No tracing @ KMT_DH_DEVICE_DETAILS.FILE_OPEN := FALSE; @ No file open initially @ KMT_DH_DEVICE_DETAILS.INPUT_PARITY := 4; @ No parity @ KMT_DH_DEVICE_DETAILS.OUTPUT_PARITY := 4; @ NO parity @ KMT_DH_DEVICE_DETAILS.PAUSE := 0; @ NO pause @ KMT_FH_RECORD_DETAILS.FILE_OPEN := FALSE; @ No file open initially @ KMT_FH_RECORD_DETAILS.TEXT_TYPE := 0; @ EBCDIC text @ KMT_FH_FILE_STATISTICS := (0,0); @ Zero record transfers @ KMT_PP_LOCAL_CONFG_PARAMS := (X"1E", @ MARK - Record Seperator @ 80, @ MAXL @ 0, @ TIME - No timeout @ 0, @ NPAD - No padding @ X"00", @ PADC - Null @ X"0D", @ EOL - Carriage Return @ X"23", @ QCTL - Hash # @ X"26", @ QBIN - Ampersand & @ X"31", @ CHKT - Single check sum @ X"00", @ REPT - Not supported @ X'00'); @ CAPAS - Not supported @ KMT_PP_REMOTE_CONFG_PARAMS := (X"1E", @ MARK - Record Seperator @ 80, @ MAXL @ 0, @ TIME - No timeout @ 0, @ NPAD - No padding @ X"00", @ PADC - Null @ X"0D", @ EOL - Carriage Return @ X"23", @ QCTL - Hash # @ X"26", @ QBIN - Ampersand & @ X"31", @ CHKT - Single check sum @ X"00", @ REPT - Not supported @ X'00'); @ CAPAS - Not supported @ KMT_PP_PACKET_STATISTICS := (0,0); @ Zero packet transfers @ END; @ KMT_SP_SET_DEFAULTS @ ***PAGE GLOBAL STATIC () PROC KMT_SP_CHAR_TO_HEX IS ( REF () BYTE HEX_DIGITS, REF () BYTE HEX_STRING, REF INT HEX_STRING_LENGTH, RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to convert a string representing hexadecimal digits *@ @* from character to the hexadecimal notation. *@ @* The area referenced by HEX_DIGITS contains the string representing the *@ @* hexadecimal digits and HEX_STRING references an area to contain the *@ @* hexadecimal string. *@ @* The number of hexadecimal characters returned in HEX_STRING is returned *@ @* in the area referenced by HEX_STRING_LENGTH. *@ @* If a non hexadecimal digit is detected then HEX_STRING_LENGTH is returned *@ @* zero and resultcode KMT_SP_NOT_HEX is returned. *@ @* If the area referenced by HEX_STRING is not large enough to contain the *@ @* hexadecimal string then HEX_STRING_LENGTH is returned containing the size *@ @* required and resultcode KMT_SP_STRING_TOO_BIG is returned *@ @* *@ @******************************************************************************@ BEGIN ***PAGE SIM PROC KMT_SP_HEX IS ( 2-BYTE HEX_DIGITS) BYTE: @******************************************************************************@ @* *@ @* This procedure is used to return a hexadecimal string from the two byte *@ @* hexadecimal representation supplied in HEX_STRING. *@ @* *@ @******************************************************************************@ BEGIN (2) BYTE HEX_DIGITS_COPY := HEX_DIGITS; FOR I TO 1 DO REF BYTE HEX_DIGIT IS HEX_DIGITS_COPY (I); IF (HEX_DIGIT GE "A") AND (HEX_DIGIT LE "F") THEN @ In range "A" to "F" @ HEX_DIGIT := HEX_DIGIT + X"09" FI; HEX_DIGIT := HEX_DIGIT & X"0F"; @ In range X"00" to X"0F" @ REPEAT; (W'PACKS (0, HEX_DIGITS_COPY, 0, NIL)) SCALE -4 END; @ KMT_SP_HEX @ ***PAGE INT KMT_SP_NOT_HEX IS 80050, KMT_SP_STRING_TOO_BIG IS 80051; INT HEX_DIGITS_LENGTH IS LENGTH HEX_DIGITS; RESULT := UNLESS ( () BYTE NON_HEX_BIT_MAP IS (X"FFFFFFFF FFFFFFFF" X"FFFFFFFF FFFFFFFF" X"81FFFFFF FFFFFFFF" X"81FFFFFF FFFF003F"); @ Allow lower and upper case @ CHECK (NON_HEX_BIT_MAP, HEX_DIGITS, 0, NIL) ) THEN @ Non hex digit in string @ HEX_STRING_LENGTH := 0; KMT_SP_NOT_HEX ELSF ( HEX_STRING_LENGTH := (HEX_DIGITS_LENGTH + 1) / 2; HEX_STRING_LENGTH GT LENGTH HEX_STRING ) THEN @ Return string too small @ KMT_SP_STRING_TOO_BIG ELSE @ Convert to hex @ INT HEX_DIGITS_INDEX := IF ((WORD:HEX_DIGITS_LENGTH) & 1) EQ 1 THEN @ Odd number of hex digits @ HEX_STRING(0) := KMT_SP_HEX ( HEX_DIGITS(0)); 1 ELSE 0 FI; FOR I FROM HEX_DIGITS_INDEX UNTIL HEX_DIGITS_INDEX GE HEX_DIGITS_LENGTH DO HEX_STRING (I) := KMT_SP_HEX (HEX_DIGITS(HEX_DIGITS_INDEX SIZE 2)); HEX_DIGITS_INDEX := HEX_DIGITS_INDEX + 2 REPEAT; 0 FI END; @ KMT_SP_CHAR_TO_HEX @ ***PAGE GLOBAL STATIC () PROC KMT_SP_CONVERT_TO_BINARY IS (REF KMT_WORD W) WORD: @ Converts Kermit word or string to a binary number @ IF W REF NIL THEN @ not given @ -1 ELSF (() BYTE BIT_MAP IS X"FFFFFFFF FFFFFFFF" X"FFFFFFFF FFFFFFFF" X"FFFFFFFF FFFFFFFF" X"FFFFFFFF FFFF003F"; CHECK(BIT_MAP,W,0,NIL) ) THEN @ numeric @ I'PACKS(0,W,0,NIL) ELSF LENGTH W < 2 OR W(0) NE "X" THEN @ not hex - invalid @ -1 ELSE (4) BYTE HEX; INT HEX_LEN,RESULT; KMT_SP_CHAR_TO_HEX(W(1::),HEX,HEX_LEN,RESULT); IF RESULT NE 0 OR HEX_LEN < 1 THEN @ invalid hex digits @ -1 ELSE @ VALID HEX NUMBER @ HEX(SIZE HEX_LEN) FI FI ; @ KMT_SP_CONVERT_TO_BINARY @ ***PAGE GLOBAL STATIC () PROC KMT_SP_CONVERT_TO_UPPER_CASE IS ( REF () BYTE BUFFER): @******************************************************************************@ @* *@ @* This procedure is used to convert lowercase EBCDIC alphabetic characters *@ @* to uppercase EBCDIC. *@ @* The characters to be case converted are read from and the case converted *@ @* characters are written to the area referenced by BUFFER. *@ @* *@ @******************************************************************************@ UNLESS (BUFFER IS NIL) OR (LENGTH BUFFER EQ 0) DO (256) BYTE UPPER_CASE_TT IS X"00010203 04050607 08090A0B 0C0D0E0F" X"10111213 14151617 18191A1B 1C1D1E1F" X"20212223 24252627 28292A2B 2C2D2E2F" X"30313233 34353637 38393A3B 3C3D3E3F" X"40414243 44454647 48494A4B 4C4D4E4F" X"50515253 54555657 58595A5B 5C5D5E5F" X"60616263 64656667 68696A6B 6C6D6E6F" X"70717273 74757677 78797A7B 7C7D7E7F" X"80C1C2C3 C4C5C6C7 C8C98A8B 8C8D8E8F" X"90D1D2D3 D4D5D6D7 D8D99A9B 9C9D9E9F" X"A0A1E2E3 E4E5E6E7 E8E9AAAB ACADAEAF" X"B0B1B2B3 B4B5B6B7 B8B9BABB BCBDBEBF" X"C0C1C2C3 C4C5C6C7 C8C9CACB CCCDCECF" X"D0D1D2D3 D4D5D6D7 D8D9DADB DCDDDEDF" X"E0E1E2E3 E4E5E6E7 E8E9EAEB ECEDEEEF" X"F0F1F2F3 F4F5F6F7 F8F9FAFB FCFDFEFF"; TRANSLATE (UPPER_CASE_TT,BUFFER,0,NIL); FI ; @ KMT_SP_CONVERT_TO_UPPERCASE @ ***PAGE GLOBAL STATIC () PROC KMT_SP_ASK_MESSAGE IS ( REF () BYTE PROMPT, REF () BYTE MESSAGE, REF LONG INT LENGTH_MESSAGE, BOOL LOG_PROMPT, RESPONSE RESULT): @******************************************************************************@ @* *@ @* This procedure is used to output a prompt to the users terminal and read a *@ @* reply to the prompt. Logging of the prompt and reply to the journal is *@ @* turned off. *@ @* *@ @******************************************************************************@ BEGIN INT RC_DISCARDED; CTM_JS_BEGIN (RESULT); IF RESULT LE 0 THEN @ Resource block created @ UNLESS LOG_PROMPT DO () BYTE NAME := "NOLASKS"; () REF () BYTE NAMES := DISPLAY(NAME); (0) BYTE ZLR; SET_OPTIONS (NAMES,ZLR,RC_DISCARDED) FI; ASK_MESSAGE (PROMPT,MESSAGE,LENGTH_MESSAGE,RESULT); CTM_JS_END (RC_DISCARDED) @ End resource block @ FI END; @ KMT_SP_ASK_MESSAGE @ ***PAGE GLOBAL STATIC () PROC KMT_SP_LOG_TRACE_MESSAGE IS ( INT TYPE, REF () KMT_MTM_VALUES PARAMS): @******************************************************************************@ @* *@ @* This procedure is used to log a trace message (printed in hex) to the job *@ @* journal. *@ @* TYPE specifies the type of trace message and PARAMS references a list of *@ @* parameters to be used in the expansion of the message. *@ @* *@ @******************************************************************************@ BEGIN INT PARAMS_LENGTH IS IF PARAMS IS NIL THEN 0 ELSE LENGTH PARAMS FI; INT MTM_AREA_LENGTH IS 4 + PARAMS_LENGTH; (MTM_AREA_LENGTH) KMT_MTM_VALUES MTM_AREA; INT MTM_TEXT_NUMBER := TYPE, MTM_REPLY, MTM_MESSAGE_LENGTH; (100) BYTE MTM_MESSAGE; (2) REF () BYTE MTM_RECALL_DATA; MTM_AREA(SIZE 4) := (MTM_MESSAGE AS KMT_MTM_VALUES.RVB_VALUE, MTM_MESSAGE_LENGTH AS KMT_MTM_VALUES.RI_VALUE, MTM_RECALL_DATA AS KMT_MTM_VALUES.RVRVB_VALUE, (L'PARAMS_LENGTH) AS KMT_MTM_VALUES.LI_VALUE); IF PARAMS_LENGTH GT 0 THEN MTM_AREA(4::) := PARAMS FI; WHILE ( INT RC_DISCARDED; MTM_REPLY := KMT_SP_MTM (MTM_TEXT_NUMBER,MTM_AREA); IF MTM_REPLY NE -2 THEN @ Expanded message returned @ REF () BYTE MESSAGE IS IF MTM_REPLY EQ -3 THEN @ Returned in recall data @ MTM_TEXT_NUMBER := 0; MTM_RECALL_DATA(0) ELSE @ Returned in message buffer @ MTM_TEXT_NUMBER := MTM_REPLY; MTM_MESSAGE(SIZE MTM_MESSAGE_LENGTH) FI; CTM_LOG (3, 2, @ Log to journal only @ MESSAGE, RC_DISCARDED) ELSE @ No message data @ MTM_TEXT_NUMBER := 0 FI; MTM_TEXT_NUMBER NE 0 ) DO SKIP REPEAT END; @ KMT_SP_LOG_TRACE_MESSAGE @ ***PAGE GLOBAL STATIC () PROC KMT_SP_STANDARDISE_FILENAME IS (REF KMT_WORD FILENAME, INT STD_FORM): @ standardises filenames (if reqd) according to STD_FORM: @ @ @ @ VME_TERM - terminal name of filename, i.e. part after rightmost dot @ @ VME_STD - remove suffix from filename which should be in Kermit @ @ normal form as sent in packet by remote Kermit @ @ KMT_STD - convert filename to Kermit normal form, i.e. name.type @ @ @ @ in each case any file generation number will be removed and all lower @ @ case alphabetic characters converted to upper case. any non-alphanumeric @ @ characters (except fullstop) will be converted to X @ BEGIN IF TRANSLATE_FILENAME THEN @ filename translation required @ REF () BYTE NAME,REM; NAME := FILENAME; REM := FILENAME; UNTIL SCANUNQ(".",REM,0,REM) @ locate fullstop @ DO INT NAME_LEN IS LENGTH NAME, REM_LEN IS LENGTH REM; REM := IF REM_LEN > 1 THEN REM(1::) @ strip off fullstop @ ELSE REM(SIZE 0) @ "." last character @ FI; NAME := IF NOT SCANUNQ(".",REM,0,NIL) @ if more fullstops @ THEN REM @ continue @ ELSF STD_FORM = VME_TERM THEN REM @ bit after fullstop @ ELSF STD_FORM = VME_STD THEN NAME(SIZE(NAME_LEN-REM_LEN)) @ bit before fullstop@ ELSE NAME @ KMT_STD @ @ i.e. name.type @ FI REPEAT; SCANUNQ("(",NAME,0,REM); @ locate generation number (if present) @ FILENAME := NAME(SIZE (LENGTH NAME - LENGTH REM)); @ remove gen no @ IF LENGTH FILENAME > 0 THEN @ standardise characters @ (256) BYTE STD_CHAR_TT IS X"E7E7E7E7 E7E7E7E7 E7E7E7E7 E7E7E7E7" X"E7E7E7E7 E7E7E7E7 E7E7E7E7 E7E7E7E7" X"E7E7E7E7 E7E7E7E7 E7E7E7E7 E7E7E7E7" X"E7E7E7E7 E7E7E7E7 E7E7E7E7 E7E7E7E7" X"E7E7E7E7 E7E7E7E7 E7E7E74B E7E7E7E7" X"E7E7E7E7 E7E7E7E7 E7E7E7E7 E7E7E7E7" X"E7E7E7E7 E7E7E7E7 E7E7E7E7 E7E7E7E7" X"E7E7E7E7 E7E7E7E7 E7E7E7E7 E7E7E7E7" X"E7C1C2C3 C4C5C6C7 C8C9E7E7 E7E7E7E7" X"E7D1D2D3 D4D5D6D7 D8D9E7E7 E7E7E7E7" X"E7E7E2E3 E4E5E6E7 E8E9E7E7 E7E7E7E7" X"E7E7E7E7 E7E7E7E7 E7E7E7E7 E7E7E7E7" X"E7C1C2C3 C4C5C6C7 C8C9E7E7 E7E7E7E7" X"E7D1D2D3 D4D5D6D7 D8D9E7E7 E7E7E7E7" X"E7E7E2E3 E4E5E6E7 E8E9E7E7 E7E7E7E7" X"F0F1F2F3 F4F5F6F7 F8F9E7E7 E7E7E7E7"; TRANSLATE(STD_CHAR_TT,FILENAME,0,NIL) ELSE @ invalid name @ FILENAME := NIL FI FI END ; @ KMT_SP_STANDARDISE_FILENAME @ ***PAGE GLOBAL STATIC () PROC KMT_SP_GET_WORD IS (REF KMT_STRING S) KMT_WORD: @ extract word (delimited by spaces) from string, advance pointer over word @ BEGIN KMT_STRING S1,S2; IF SCANEQ(" ",S,0,S1) @ skip leading spaces @ THEN NIL @ end of line, return null word @ ELSE SCANUNQ(" ",S1,0,S2); @ find next space (end of word) @ S := S2; @ advance pointer @ S1(SIZE LENGTH S1 - LENGTH S2) @ return word @ FI END ; @ KMT_SP_GET_WORD @ ***PAGE GLOBAL STATIC () PROC KMT_SP_CHECK_VME_CHAR IS (WORD CHAR,WORD IO_FLAG,RESPONSE RESULT): @ check that CHAR is acceptable for VME I/O @ BEGIN IF CHAR = 127 @ ASCII DEL @ THEN RESULT := 0 ELSE ()BYTE X := DISPLAY (CHAR); REF () BYTE B := X; () BYTE CHECK_BITS IS IF ASG_ROUTE AND IO_FLAG = 0 THEN X"FFFF0FFF" @ in via ASG @ ELSF ASG_ROUTE THEN X"A7DFFFFF" @ out via ASG @ ELSF IO_FLAG = 0 THEN X"0183087F" @ in via CSC or NIC @ ELSE X"A7DFFFFF" @ out via CSC or NIC @ FI; RESULT := IF CHECK(CHECK_BITS,B,1,NIL) THEN 85936 ELSE 0 FI FI END ; @ KMT_SP_CHECK_VME_CHAR @ ENDMODULE @ KMT_SP_MODULE @ $$$$ KMT_UI_MODULE MODULE KMT_UI_MODULE; @ Mode declarations @ MODE KMT_BUFFER IS (96)BYTE; MODE KMT_STRING IS REF()BYTE; MODE KMT_WORD IS REF()BYTE; 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); 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_FH_RECORD_DETAILS_S IS STRUCT (BOOL FILE_OPEN, NEW_RECORD, END_OF_FILE, WORD TEXT_TYPE, @ 0 = EBCDIC @ @ 1 = IA5 @ @ 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_PP_CONFG_PARAMS_S IS STRUCT (BYTE MARK, MAXL, TIME, NPAD, PADC, EOL, QCTL, QBIN, CHKT, REPT, 4-BYTE CAPAS); MODE KMT_TRACE_FLAGS_S IS WORD STRUCT (BIT PH_TRACING, PP_TRACING, FH_TRACING, DH_TRACING, 28-BIT SPARE); MODE KMT_FH_FILE_STATISTICS_S IS STRUCT (INT INPUT_TOTAL, INT OUTPUT_TOTAL); MODE KMT_PP_PACKET_STATISTICS_S IS STRUCT (INT INPUT_TOTAL, INT OUTPUT_TOTAL); MODE KMT_STATISTICS_S IS STRUCT (REF KMT_FH_FILE_STATISTICS_S FH_FILE_STATISTICS, REF KMT_PP_PACKET_STATISTICS_S PACKET_STATISTICS); @ External procedures @ EXT PROC (INT,RESPONSE) KMT_MESSAGE; EXT PROC (INT,REF()KMT_MTM_VALUES) INT KMT_HELP_MTM; EXT PROC (INT,REF()KMT_MTM_VALUES) INT KMT_SP_MTM; EXT PROC (REF KMT_STRING) KMT_WORD KMT_SP_GET_WORD, PROC (REF () BYTE) KMT_SP_CONVERT_TO_UPPER_CASE, PROC (()BYTE,REF()BYTE,REF LONG INT,BOOL,RESPONSE) KMT_SP_ASK_MESSAGE, PROC (REF KMT_WORD) WORD KMT_SP_CONVERT_TO_BINARY, PROC (WORD,WORD,RESPONSE) KMT_SP_CHECK_VME_CHAR; EXT PROC (WORD,WORD,REF()BYTE,RESPONSE) CTM_LOG; @ External constants @ EXT INT UNSET,EXIT; @ miscellaneous constants @ EXT INT SERVER_MODE,RECEIVE_MODE,SEND_MODE,COMMAND_MODE; EXT INT REC_SERVER_IDLE,REC_INIT,SEND_INIT,COMPLETE,ABORT; @ protocol handler @ @ states @ EXT REF INT EXIT_STATE, @ controls main Kermit loop @ KMT_CURRENT_MODE, @ Server/Receive/Send/Command @ KMT_PH_STATE; @ Protocol Handler state @ EXT (256) BYTE EBCDIC_TO_ASCII, @ Translation tables @ ASCII_TO_EBCDIC; EXT REF KMT_STRING KMT_PH_INPUT_PACKET_DATA; EXT REF KMT_BUFFER KMT_VME_FILE_BUF,KMT_REM_FILE_BUF,KMT_INPUT_BUF; EXT REF KMT_WORD KMT_VME_FILE,KMT_REM_FILE; EXT REF()KMT_MTM_VALUES KMT_MTM_AREA; EXT REF INT MAXTRY,RETRY_COUNT,RETRY_TOTAL,TIMEOUT_TOTAL; EXT REF INT FILE_OPTION; EXT REF WORD DELAY; EXT REF BOOL TRANSLATE_FILENAME; EXT REF BOOL SAVE_INCOMPLETE_FILE; EXT REF KMT_DH_DEVICE_DETAILS_S KMT_DH_DEVICE_DETAILS; EXT REF KMT_FH_RECORD_DETAILS_S KMT_FH_RECORD_DETAILS; EXT REF KMT_PP_CONFG_PARAMS_S KMT_PP_LOCAL_CONFG_PARAMS, KMT_PP_REMOTE_CONFG_PARAMS; EXT REF KMT_TRACE_FLAGS_S KMT_TRACE_FLAGS; EXT REF KMT_STATISTICS_S KMT_STATISTICS; GLOBAL STATIC () PROC KMT_UI IS (RESPONSE RESULT): @ requests command from user and executes command @ BEGIN LONG INT STRLEN; @ length of input @ INT RC_IGNORED; @ response variable @ KMT_STRING KMT_CMD_BUF, @ command input string @ KMT_PARSE; @ pointer for parsing command string @ (10)KMT_MTM_VALUES HELP_MTM_AREA; (80)BYTE HELP_TEXT; INT HELP_TEXT_LEN; (2)REF()BYTE HELP_RECALL_DATA; INT MARK_PARAM IS 0, EOL_PARAM IS 1, PADC_PARAM IS 2; @ support procs @ SIM PROC CHECK_AND_SET_PARAM IS (INT PARAM_CODE, WORD VALUE, WORD P_FLAG, RESPONSE RESULT): @ checks new value for MARK/EOL/PADC doesn't conflict with EOL/PADC/ @ @ MARK (as appropriate) and that the value is acceptable to VME I/O @ BEGIN IF VALUE > 31 AND VALUE NE 127 THEN @ not a control character @ RESULT := 85935 ELSE INT PMATCH; REF KMT_PP_CONFG_PARAMS_S CONFG_PARAMS IS IF P_FLAG = 0 THEN KMT_PP_REMOTE_CONFG_PARAMS @ receive @ ELSE KMT_PP_LOCAL_CONFG_PARAMS @ send @ FI; RESULT := UNSET; IF VALUE = CONFG_PARAMS.MARK @ check if value matches any param @ THEN PMATCH := MARK_PARAM ELSF VALUE = CONFG_PARAMS.EOL THEN PMATCH := EOL_PARAM ELSF VALUE = CONFG_PARAMS.PADC THEN PMATCH := PADC_PARAM ELSF KMT_SP_CHECK_VME_CHAR(VALUE,P_FLAG,RESULT); RESULT = 0 THEN @ character ok for VME I/O so set parameter @ CASE PARAM_CODE THEN CONFG_PARAMS.MARK := VALUE ELSE CONFG_PARAMS.EOL := VALUE ELSE CONFG_PARAMS.PADC := VALUE ESAC; RESULT := 0 FI; IF RESULT = UNSET THEN IF PMATCH = PARAM_CODE THEN @ matched current value, ignore @ RESULT := 0 ELSE @ conflict with another parameter @ KMT_MTM_AREA(7) := PMATCH AS KMT_MTM_VALUES.RI_VALUE; RESULT := 85937 FI FI FI END ; @ CHECK_AND_SET_PARAM @ SIM PROC EXPAND_HELP IS (INT MSG_NO) INT: @ expand help text until reply is -2 (no message found) or 0 (halted @ @ at end of message) or > 0 (halt code returned). @ BEGIN INT M := MSG_NO, REPLY := UNSET; @ -1 @ WHILE REPLY = UNSET DO REPLY := KMT_HELP_MTM(M,HELP_MTM_AREA); IF REPLY = -1 OR REPLY = 0 THEN M := REPLY; CTM_LOG(3,10,HELP_TEXT(SIZE HELP_TEXT_LEN),RC_IGNORED) FI REPEAT; REPLY @ return last reply @ END ; @ EXPAND_HELP @ @ procedures for executing commands @ SIM PROC KMT_UI_SERVER IS GROUP KMT_UI_EXEC(RESPONSE RESULT): @ SERVER command, Syntax: SERVER @ @ selects Kermit Server mode @ @ (not implemented in Server mode) @ IF KMT_CURRENT_MODE NE SERVER_MODE THEN KMT_CURRENT_MODE := SERVER_MODE; KMT_PH_STATE := REC_SERVER_IDLE; RETRY_COUNT := RETRY_TOTAL := TIMEOUT_TOTAL := 0; VAL KMT_STATISTICS.PACKET_STATISTICS := (0,0); RESULT := 0 ELSE RESULT := 89021 @ not implemented in Server mode @ FI ; @ KMT_UI_SERVER @ SIM PROC KMT_UI_RECEIVE IS GROUP KMT_UI_EXEC(RESPONSE RESULT): @ RECEIVE command, Syntax: RECEIVE [VME-filename] @ @ prepares VME kermit for the arrival of a file which will be @ @ saved with VME filename if specified, or with the filename sent @ @ by the remote Kermit @ @ (not implemented in Server mode) @ IF KMT_CURRENT_MODE NE SERVER_MODE THEN @ check for optional filename @ KMT_VME_FILE := KMT_SP_GET_WORD(KMT_PARSE); @ if present, copy to filename buffer @ UNLESS KMT_VME_FILE REF NIL DO KMT_VME_FILE := KMT_VME_FILE_BUF(SIZE LENGTH KMT_VME_FILE) := KMT_VME_FILE FI; @ set Receive mode and initial protocol handler state @ KMT_CURRENT_MODE := RECEIVE_MODE; KMT_PH_STATE := REC_INIT; RETRY_COUNT := RETRY_TOTAL := TIMEOUT_TOTAL := 0; VAL KMT_STATISTICS.PACKET_STATISTICS := (0,0); RESULT := 0 ELSE RESULT := 89021 @ not implemented in Server mode @ FI ; @ KMT_UI_RECEIVE @ SIM PROC KMT_UI_SEND IS GROUP KMT_UI_EXEC(RESPONSE RESULT): @ SEND command, Syntax: SEND VME-filename [remote-filename] @ @ sends the VME file to the remote Kermit with remote filename if @ @ specified otherwise with VME filename @ @ (not implemented in Server mode) @ IF KMT_CURRENT_MODE NE SERVER_MODE THEN @ check for mandatory filename @ KMT_VME_FILE := KMT_SP_GET_WORD(KMT_PARSE); IF NOT (KMT_VME_FILE REF NIL) THEN @ copy to filename buffer @ KMT_VME_FILE := KMT_VME_FILE_BUF(SIZE LENGTH KMT_VME_FILE) := KMT_VME_FILE; @ check for optional remote filename @ KMT_REM_FILE := KMT_SP_GET_WORD(KMT_PARSE); @ if present copy to buffer @ UNLESS KMT_REM_FILE REF NIL DO KMT_REM_FILE := KMT_REM_FILE_BUF(SIZE LENGTH KMT_REM_FILE) := KMT_REM_FILE FI; @ set Send mode and initial protocol handler state @ KMT_CURRENT_MODE := SEND_MODE; KMT_PH_STATE := SEND_INIT; RETRY_COUNT := RETRY_TOTAL := TIMEOUT_TOTAL := 0; VAL KMT_STATISTICS.PACKET_STATISTICS := (0,0); RESULT := 0 ELSE RESULT := -85010 @ VME filename must be present @ FI ELSE RESULT := 89021 @ not implemented in Server mode @ FI ; @ KMT_UI_SEND @ SIM PROC KMT_UI_HELP IS GROUP KMT_UI_EXEC(RESPONSE RESULT): @ HELP command, Syntax: HELP [command [argument(s)] ] @ @ provides on-line help for Kermit commands @ @ (not implemented in Server mode) @ IF KMT_CURRENT_MODE NE SERVER_MODE THEN INT HELP_MSG_NO := 1, @ start of help info @ P1 := 0, @ indicates mtm call with command params @ HELP_REPLY; @ set up message text parameter area @ HELP_MTM_AREA(SIZE 4) := (HELP_TEXT AS KMT_MTM_VALUES.RVB_VALUE, HELP_TEXT_LEN AS KMT_MTM_VALUES.RI_VALUE, HELP_RECALL_DATA AS KMT_MTM_VALUES.RVRVB_VALUE, P1 AS KMT_MTM_VALUES.RI_VALUE); @ obtain any command line parameters @ FOR I FROM 4 TO 9 DO KMT_WORD HELP_ARG := KMT_SP_GET_WORD(KMT_PARSE); KMT_SP_CONVERT_TO_UPPER_CASE(HELP_ARG); HELP_MTM_AREA(I) := HELP_ARG AS KMT_MTM_VALUES.RVB_VALUE REPEAT; @ expand help until all done (0) or none found (-2) @ WHILE HELP_REPLY := EXPAND_HELP(HELP_MSG_NO); HELP_REPLY > 0 DO @ halt code returned, text is prompt, get response @ KMT_SP_ASK_MESSAGE(HELP_TEXT(SIZE HELP_TEXT_LEN), KMT_INPUT_BUF,STRLEN,FALSE,RC_IGNORED); P1 := 1; @ indicates mtm call with menu selection @ HELP_MTM_AREA(3) := P1 AS KMT_MTM_VALUES.RI_VALUE; HELP_MTM_AREA(4) := KMT_INPUT_BUF(SIZE S'STRLEN) AS KMT_MTM_VALUES.RVB_VALUE; HELP_MSG_NO := HELP_REPLY REPEAT; RESULT := 0 ELSE RESULT := 89021 @ not implemented in Server mode @ FI ; @ KMT_UI_HELP @ SIM PROC KMT_UI_EXIT IS GROUP KMT_UI_EXEC(RESPONSE RESULT): @ EXIT command, Syntax: EXIT @ @ terminates Kermit execution @ BEGIN EXIT_STATE := EXIT; @ set exit state @ IF KMT_CURRENT_MODE = SERVER_MODE THEN KMT_PH_STATE := COMPLETE FI; RESULT := 0 END ; @ KMT_UI_EXIT @ SIM PROC KMT_UI_SET IS GROUP KMT_UI_EXEC(RESPONSE RESULT): @ SET command, Syntax: SET [{SEND/RECEIVE}] parameter value @ @ sets Kermit parameters @ BEGIN KMT_WORD ARG; WORD P_FLAG,PARAM,OPTION; RESULT := 0; ARG := KMT_SP_GET_WORD(KMT_PARSE); IF ARG REF NIL THEN @ incomplete command @ RESULT := 85932 ELSF KMT_SP_CONVERT_TO_UPPER_CASE(ARG); KMT_MTM_AREA(4) := ARG AS KMT_MTM_VALUES.RVB_VALUE; P_FLAG := KMT_SP_MTM(5100,KMT_MTM_AREA); P_FLAG NE W'UNSET THEN @ SET SEND/RECEIVE command @ ARG := KMT_SP_GET_WORD(KMT_PARSE); IF ARG REF NIL THEN @ incomplete command @ RESULT := 85932 ELSF KMT_SP_CONVERT_TO_UPPER_CASE(ARG); KMT_MTM_AREA(5) := ARG AS KMT_MTM_VALUES.RVB_VALUE; PARAM := KMT_SP_MTM(5120,KMT_MTM_AREA); PARAM = 921 THEN @ invalid SEND/RECEIVE parameter @ RESULT := 85921 ELSF ARG := KMT_SP_GET_WORD(KMT_PARSE); ARG REF NIL THEN @ incomplete command @ RESULT := 85932 ELSE KMT_SP_CONVERT_TO_UPPER_CASE(ARG); KMT_MTM_AREA(6) := ARG AS KMT_MTM_VALUES.RVB_VALUE; CASE PARAM THEN @ 0 - START-OF-PACKET @ OPTION := KMT_SP_CONVERT_TO_BINARY(ARG); CHECK_AND_SET_PARAM(MARK_PARAM,OPTION,P_FLAG,RESULT) ELSE @ 1 - PACKET-LENGTH @ WORD DH_LEN,NPAD; IF P_FLAG = 0 THEN @ RECEIVE @ DH_LEN := KMT_DH_DEVICE_DETAILS.MAX_INPUT_LENGTH; NPAD := KMT_PP_LOCAL_CONFG_PARAMS.NPAD ELSE DH_LEN := KMT_DH_DEVICE_DETAILS.MAX_OUTPUT_LENGTH; NPAD := KMT_PP_REMOTE_CONFG_PARAMS.NPAD FI; OPTION := KMT_SP_CONVERT_TO_BINARY(ARG); IF OPTION < 30 OR OPTION > 94 OR OPTION > DH_LEN THEN @ invalid PACKET-LENGTH @ RESULT := 85931 ELSF (OPTION + NPAD) > DH_LEN THEN @ padding + packet length exceeds device line length @ RESULT := 85934 ELSF @ set parameter @ P_FLAG = 0 THEN @ RECEIVE @ KMT_PP_LOCAL_CONFG_PARAMS.MAXL := OPTION ELSE @ SEND @ KMT_PP_REMOTE_CONFG_PARAMS.MAXL := OPTION FI ELSE @ 2 - TIMEOUT @ OPTION := KMT_SP_CONVERT_TO_BINARY(ARG); IF OPTION > 94 THEN @ invalid TIMEOUT @ RESULT := 85931 ELSF @ set parameter @ P_FLAG = 0 THEN @ RECEIVE @ KMT_PP_REMOTE_CONFG_PARAMS.TIME := OPTION ELSE @ SEND @ KMT_PP_LOCAL_CONFG_PARAMS.TIME := OPTION FI ELSE @ 3 - END-OF-LINE @ OPTION := KMT_SP_CONVERT_TO_BINARY(ARG); CHECK_AND_SET_PARAM(EOL_PARAM,OPTION,P_FLAG,RESULT) ELSE @ 4 - PADDING @ WORD DH_LEN,MAXL; IF P_FLAG = 0 THEN @ RECEIVE @ DH_LEN := KMT_DH_DEVICE_DETAILS.MAX_INPUT_LENGTH; MAXL := KMT_PP_LOCAL_CONFG_PARAMS.MAXL ELSE @ SEND @ DH_LEN := KMT_DH_DEVICE_DETAILS.MAX_OUTPUT_LENGTH; MAXL := KMT_PP_REMOTE_CONFG_PARAMS.MAXL FI; OPTION := KMT_SP_CONVERT_TO_BINARY(ARG); IF OPTION > 94 OR OPTION > DH_LEN THEN @ invalid PADDING @ RESULT := 85931 ELSF (OPTION + MAXL) > DH_LEN THEN @ padding + packet length exceeds device line length @ RESULT := 85934 ELSF @ set parameter @ P_FLAG = 0 THEN @ RECEIVE @ KMT_PP_LOCAL_CONFG_PARAMS.NPAD := OPTION ELSE @ SEND @ KMT_PP_REMOTE_CONFG_PARAMS.NPAD := OPTION FI ELSE @ 5 - PAD-CHARACTER @ OPTION := KMT_SP_CONVERT_TO_BINARY(ARG); CHECK_AND_SET_PARAM(PADC_PARAM,OPTION,P_FLAG,RESULT) ELSE @ 6 - QUOTE @ REF KMT_PP_CONFG_PARAMS_S CONFG_PARAMS IS IF P_FLAG = 0 THEN @ RECEIVE @ KMT_PP_REMOTE_CONFG_PARAMS ELSE @ SEND @ KMT_PP_LOCAL_CONFG_PARAMS FI; OPTION := IF LENGTH ARG > 1 THEN @ may be decimal or hex @ KMT_SP_CONVERT_TO_BINARY(ARG) ELSE @ EBCDIC character @ EBCDIC_TO_ASCII(ARG) FI; IF OPTION < 32 OR OPTION > 126 THEN @ not a printable character @ RESULT := 85931 ELSF CONFG_PARAMS.QBIN = OPTION THEN @ QUOTE and EIGTH-BIT-PREFIX characters equal @ RESULT := 85933 ELSE @ set parameter @ CONFG_PARAMS.QCTL := OPTION FI ELSE @ 7 - EIGTH-BIT-PREFIX @ REF KMT_PP_CONFG_PARAMS_S CONFG_PARAMS IS IF P_FLAG = 0 THEN @ RECEIVE @ KMT_PP_REMOTE_CONFG_PARAMS ELSE @ SEND @ KMT_PP_LOCAL_CONFG_PARAMS FI; OPTION := IF LENGTH ARG > 1 THEN @ may be decimal or hex @ KMT_SP_CONVERT_TO_BINARY(ARG) ELSE @ EBCDIC character @ EBCDIC_TO_ASCII(ARG) FI; IF OPTION < 32 OR OPTION > 126 OR (OPTION > 62 AND OPTION < 96) THEN @ not a printable character @ RESULT := 85931 ELSF CONFG_PARAMS.QCTL = OPTION THEN @ QUOTE and EIGTH-BIT-PREFIX characters equal @ RESULT := 85933 ELSE @ set parameter @ CONFG_PARAMS.QBIN := OPTION FI DEFAULT @ invalid SEND/RECEIVE parameter @ RESULT := 85921 ESAC FI ELSF P_FLAG := KMT_SP_MTM(5110,KMT_MTM_AREA); P_FLAG = 920 THEN @ invalid SET parameter @ RESULT := 85920 ELSF @ SET DEBUG/DELAY/FILE/RETRY/PAUSE @ ARG := KMT_SP_GET_WORD(KMT_PARSE); ARG REF NIL THEN @ incomplete command @ RESULT := 85932 ELSE KMT_SP_CONVERT_TO_UPPER_CASE(ARG); KMT_MTM_AREA(5) := ARG AS KMT_MTM_VALUES.RVB_VALUE; CASE P_FLAG THEN @ 0 - DEBUG @ PARAM := KMT_SP_MTM(5130,KMT_MTM_AREA); IF PARAM = 921 THEN @ invalid DEBUG parameter @ RESULT := 85921 ELSF ARG := KMT_SP_GET_WORD(KMT_PARSE); ARG REF NIL THEN @ incomplete command @ RESULT := 85932 ELSF KMT_SP_CONVERT_TO_UPPER_CASE(ARG); KMT_MTM_AREA(6) := ARG AS KMT_MTM_VALUES.RVB_VALUE; OPTION := KMT_SP_MTM(5150,KMT_MTM_AREA); OPTION = 931 THEN @ invalid option @ RESULT := 85931 ELSE @ set parameter @ CASE PARAM THEN @ 0 - ALL @ KMT_TRACE_FLAGS := IF OPTION = 0 THEN @ OFF @ 0 ELSE @ ON @ -1 FI ELSE @ 1 - FILE @ KMT_TRACE_FLAGS.FH_TRACING := OPTION ELSE @ 2 - PROTOCOL @ KMT_TRACE_FLAGS.PH_TRACING := OPTION ELSE @ 3 - PACKET @ KMT_TRACE_FLAGS.PP_TRACING := OPTION ELSE @ 4 - DEVICE @ KMT_TRACE_FLAGS.DH_TRACING := OPTION DEFAULT @ invalid option @ RESULT := 85931 ESAC FI ELSE @ 1 - DELAY @ KMT_SP_CONVERT_TO_UPPER_CASE(ARG); KMT_MTM_AREA(5) := ARG AS KMT_MTM_VALUES.RVB_VALUE; OPTION := KMT_SP_CONVERT_TO_BINARY(ARG); IF OPTION < 5 OR OPTION > 300 THEN @ invalid DELAY parameter @ RESULT := 85930 ELSE @ set parameter @ DELAY := I'(OPTION) FI ELSE @ 2 - FILE @ KMT_SP_CONVERT_TO_UPPER_CASE(ARG); KMT_MTM_AREA(5) := ARG AS KMT_MTM_VALUES.RVB_VALUE; ARG := KMT_SP_GET_WORD(KMT_PARSE); IF ARG REF NIL THEN @ incomplete command @ RESULT := 85932 ELSF KMT_SP_CONVERT_TO_UPPER_CASE(ARG); KMT_MTM_AREA(6) := ARG AS KMT_MTM_VALUES.RVB_VALUE; OPTION := KMT_SP_MTM(5140,KMT_MTM_AREA); OPTION = 921 OR OPTION = 931 THEN @ invalid FILE parameter or option @ RESULT := 85000 + OPTION ELSF OPTION < 3 THEN @ TYPE - EBCDIC, ASCII, BINARY @ KMT_FH_RECORD_DETAILS.TEXT_TYPE := OPTION ELSF OPTION < 5 THEN @ NAMING @ TRANSLATE_FILENAME := (OPTION = 4) ELSF OPTION < 7 THEN @ OVERWRITE @ FILE_OPTION := IF OPTION = 5 THEN @ create mode @ 1 ELSE @ create replace mode @ 2 FI ELSF OPTION < 9 THEN @ INCOMPLETE @ SAVE_INCOMPLETE_FILE := (OPTION = 8) ELSE @ invalid FILE parameter @ RESULT := 85931 FI ELSE @ 3 - RETRY @ KMT_SP_CONVERT_TO_UPPER_CASE(ARG); KMT_MTM_AREA(5) := ARG AS KMT_MTM_VALUES.RVB_VALUE; OPTION := KMT_SP_CONVERT_TO_BINARY(ARG); IF OPTION > 10 THEN @ invalid RETRY @ RESULT := 85930 ELSE @ set parameter @ MAXTRY := OPTION + 1 FI ELSE @ 4 - PAUSE @ KMT_SP_CONVERT_TO_UPPER_CASE(ARG); KMT_MTM_AREA(5) := ARG AS KMT_MTM_VALUES.RVB_VALUE; OPTION := KMT_SP_CONVERT_TO_BINARY(ARG); IF OPTION > 50 THEN @ invalid PAUSE @ RESULT := 85930 ELSE @ set parameter @ KMT_DH_DEVICE_DETAILS.PAUSE := (I'OPTION) * 100 FI DEFAULT @ invalid SET parameter @ RESULT := 85920 ESAC FI; IF KMT_CURRENT_MODE NE SERVER_MODE AND RESULT > 0 THEN @ don't send error packet if not in server mode @ RESULT := -RESULT FI END ; @ KMT_UI_SET @ SIM PROC KMT_UI_SHOW IS GROUP KMT_UI_EXEC(RESPONSE RESULT): @ SHOW command, Syntax: SHOW @ @ displays the current values of all Kermit parameters @ @ (this variant not implemented in Server mode @ IF KMT_CURRENT_MODE NE SERVER_MODE THEN BYTE REM_QCTL := ASCII_TO_EBCDIC(KMT_PP_REMOTE_CONFG_PARAMS.QCTL), REM_QBIN := ASCII_TO_EBCDIC(KMT_PP_REMOTE_CONFG_PARAMS.QBIN), LOC_QCTL := ASCII_TO_EBCDIC(KMT_PP_LOCAL_CONFG_PARAMS.QCTL), LOC_QBIN := ASCII_TO_EBCDIC(KMT_PP_LOCAL_CONFG_PARAMS.QBIN); KMT_MTM_AREA(3 SIZE 3) := ((L'(I'DELAY)) AS KMT_MTM_VALUES.LW_VALUE, (L'(I'KMT_DH_DEVICE_DETAILS.PAUSE)/100) AS KMT_MTM_VALUES.LW_VALUE, (L'(MAXTRY-1)) AS KMT_MTM_VALUES.LI_VALUE); KMT_MESSAGE(-85821,RC_IGNORED); KMT_MTM_AREA(3 SIZE 8) := (KMT_PP_REMOTE_CONFG_PARAMS.MARK AS KMT_MTM_VALUES.RVB_VALUE, (L'KMT_PP_LOCAL_CONFG_PARAMS.MAXL) AS KMT_MTM_VALUES.LW_VALUE, (L'KMT_PP_REMOTE_CONFG_PARAMS.TIME) AS KMT_MTM_VALUES.LW_VALUE, (L'KMT_PP_LOCAL_CONFG_PARAMS.NPAD) AS KMT_MTM_VALUES.LW_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, REM_QCTL AS KMT_MTM_VALUES.RVB_VALUE, REM_QBIN AS KMT_MTM_VALUES.RVB_VALUE); KMT_MESSAGE(-85822,RC_IGNORED); KMT_MTM_AREA(3 SIZE 8) := (KMT_PP_LOCAL_CONFG_PARAMS.MARK AS KMT_MTM_VALUES.RVB_VALUE, (L'KMT_PP_REMOTE_CONFG_PARAMS.MAXL) AS KMT_MTM_VALUES.LW_VALUE, (L'KMT_PP_LOCAL_CONFG_PARAMS.TIME) AS KMT_MTM_VALUES.LW_VALUE, (L'KMT_PP_REMOTE_CONFG_PARAMS.NPAD) AS KMT_MTM_VALUES.LW_VALUE, KMT_PP_REMOTE_CONFG_PARAMS.PADC AS KMT_MTM_VALUES.RVB_VALUE, KMT_PP_REMOTE_CONFG_PARAMS.EOL AS KMT_MTM_VALUES.RVB_VALUE, LOC_QCTL AS KMT_MTM_VALUES.RVB_VALUE, LOC_QBIN AS KMT_MTM_VALUES.RVB_VALUE); KMT_MESSAGE(-85823,RC_IGNORED); KMT_MTM_AREA(3 SIZE 4) := (KMT_FH_RECORD_DETAILS.TEXT_TYPE AS KMT_MTM_VALUES.RW_VALUE, FILE_OPTION AS KMT_MTM_VALUES.RI_VALUE, (L'(WORD: (BIT: SAVE_INCOMPLETE_FILE))) AS KMT_MTM_VALUES.LW_VALUE, (L'(WORD: (BIT: TRANSLATE_FILENAME))) AS KMT_MTM_VALUES.LW_VALUE); KMT_MESSAGE(-85825,RC_IGNORED); KMT_MTM_AREA(3 SIZE 2) := (KMT_DH_DEVICE_DETAILS.MAX_INPUT_LENGTH AS KMT_MTM_VALUES.RW_VALUE, KMT_DH_DEVICE_DETAILS.MAX_OUTPUT_LENGTH AS KMT_MTM_VALUES.RW_VALUE); KMT_MESSAGE(-85826,RC_IGNORED); KMT_MTM_AREA(3 SIZE 4) := ((L'(WORD: KMT_TRACE_FLAGS.FH_TRACING)) AS KMT_MTM_VALUES.LW_VALUE, (L'(WORD: KMT_TRACE_FLAGS.PH_TRACING)) AS KMT_MTM_VALUES.LW_VALUE, (L'(WORD: KMT_TRACE_FLAGS.PP_TRACING)) AS KMT_MTM_VALUES.LW_VALUE, (L'(WORD: KMT_TRACE_FLAGS.DH_TRACING)) AS KMT_MTM_VALUES.LW_VALUE); KMT_MESSAGE(-85827,RC_IGNORED); RESULT := 0 ELSE RESULT := 85911 @ not yet implemented in Server mode @ FI ; @ KMT_UI_SHOW @ SIM PROC KMT_UI_STATISTICS IS GROUP KMT_UI_EXEC(RESPONSE RESULT): @ STATISTICS command, Syntax: STATISTICS @ @ displays statistics of last file transfer @ IF KMT_CURRENT_MODE NE SERVER_MODE THEN REF KMT_FH_FILE_STATISTICS_S FILE_STATS IS KMT_STATISTICS.FH_FILE_STATISTICS; REF KMT_PP_PACKET_STATISTICS_S PACKET_STATS IS KMT_STATISTICS.PACKET_STATISTICS; KMT_MTM_AREA(3 SIZE 6) := (PACKET_STATS.INPUT_TOTAL AS KMT_MTM_VALUES.RI_VALUE, PACKET_STATS.OUTPUT_TOTAL AS KMT_MTM_VALUES.RI_VALUE, RETRY_TOTAL AS KMT_MTM_VALUES.RI_VALUE, TIMEOUT_TOTAL AS KMT_MTM_VALUES.RI_VALUE, FILE_STATS.INPUT_TOTAL AS KMT_MTM_VALUES.RI_VALUE, FILE_STATS.OUTPUT_TOTAL AS KMT_MTM_VALUES.RI_VALUE); KMT_MESSAGE(-85820,RC_IGNORED); RESULT := 0 ELSE RESULT := 85911 @ not yet implemented in Server mode @ FI ; @ KMT_UI_STATISTICS @ SIM PROC KMT_UI_UNRECOGNISED IS GROUP KMT_UI_EXEC(RESPONSE RESULT): @ command no recognised @ IF KMT_CURRENT_MODE NE SERVER_MODE THEN RESULT := -85910 ELSE RESULT := 85910 FI ; @ KMT_UI_UNRECOGNISED @ @ command execution procedure selector: @ ()SIM PROC GROUP KMT_UI_EXEC(RESPONSE) KMT_UI_CMD IS (KMT_UI_SERVER, KMT_UI_RECEIVE, KMT_UI_SEND, KMT_UI_HELP, KMT_UI_EXIT, KMT_UI_SET, KMT_UI_SHOW, KMT_UI_STATISTICS, KMT_UI_UNRECOGNISED); KMT_WORD KMT_CMD; @ current command @ INT CMD; @ current command code @ RESULT := 0; IF KMT_CURRENT_MODE = COMMAND_MODE THEN @ prompt for command input @ KMT_SP_ASK_MESSAGE(X"15E5D4C540D285999489A36E40", @ " VME Kermit> " @ KMT_INPUT_BUF,STRLEN,TRUE,RESULT); KMT_CMD_BUF := KMT_PARSE := KMT_INPUT_BUF(SIZE S'STRLEN); ELSF LENGTH KMT_PH_INPUT_PACKET_DATA > 0 THEN @ Server mode, command in packet @ KMT_CMD_BUF := KMT_PARSE := KMT_PH_INPUT_PACKET_DATA ELSE RESULT := 89022 @ no command specified in Server mode @ FI; IF RESULT = 0 THEN KMT_CMD := KMT_SP_GET_WORD(KMT_PARSE); @ extract command @ UNLESS KMT_CMD REF NIL DO @ convert command name to upper case, validate and execute command @ KMT_SP_CONVERT_TO_UPPER_CASE(KMT_CMD); KMT_MTM_AREA(3) := KMT_CMD AS KMT_MTM_VALUES.RVB_VALUE; CMD := KMT_SP_MTM(5010,KMT_MTM_AREA(SIZE 4)); KMT_UI_CMD(CMD)(RESULT) FI FI END ; @ KMT_UI @ ENDMODULE @ KMT_UI_MODULE @ $$$$ KMT_HELP_MTM *@ KERMIT HELP SYSTEM MESSAGE TEXT MODULE @ *@ ====== ==== ====== ======= ==== ====== @ *CREATE(KMTHELPMTM) *PROC(KMTHELPMTM) *VERSION(101) *PARAMS(EXP&ICL) *LINESPLIT(SPACE) *@ N.B. NIL IS ASSUMED TO HAVE A VALUE OF -1 @ *1 @ text to validate command for which help required @ OR <-1> THEN J20, @ no command specified @ THEN J250, THEN J500, THEN J750, THEN J1000, THEN J1250, THEN J1500, THEN J1750, THEN J2000, THEN J9000 @ not a command, START-OF-PACKET info @ DEFAULT J10 @ invalid command @ ESAC > *10 @ invalid command entry @ is not a VME Kermit command. *20 @ no command specified, display menu @ Help is available for the following VME Kermit commands: (n.b. square brackets enclose optional parameters and should omitted when entering a command.) (1) SERVER : select Kermit Server mode (2) RECEIVE [VME-filename] : prepare to receive file [save as VME-filename] (3) SEND VME-filename [dest-filename] : send file [store as dest-filename] (4) HELP [command] [params] : obtain help [for command or command and parameters] (5) EXIT : exit from VME Kermit (6) SET param value : set Kermit parameter (7) SHOW : show value of all Kermit parameters (8) STATISTICS : display details of last transfer *30 @ Select command prompt @ Select command (Enter 1 to 8 or 0 if no further help required): *40 @ validate response to Select command @ THEN <>, <1> THEN J250, <2> THEN J500, <3> THEN J750, <4> THEN J1000, <5> THEN J1250, <6> THEN J1500, <7> THEN J1750, <8> THEN J2000 DEFAULT J50 ESAC > *50 @ invalid response to Select command prompt @ **** Invalid response, please re-select. *60 @ more help prompt @ Any more help required (YES/NO)? *70 @ validate more help reply @ OR THEN J20, OR THEN <> DEFAULT J60 ESAC > *250 @ SERVER command help @ SERVER command: Syntax: SERVER The SERVER command selects VME Kermit Server mode. All further commands are sent to VME Kermit by the user Kermit (running on your micro). File transfers are initiated via commands given to the micro Kermit. VME Kermit will remain in Server mode until the user Kermit instructs VME Kermit to exit to VME command level (after you have issued a FINISH command to the micro Kermit) or the user Kermit tells VME Kermit to log out (after you have issued a BYE command to the micro Kermit). WARNING: It is inadvisable to select VME Kermit Server mode if your micro Kermit doesn't have the following commands for communicating with servers: GET, BYE and FINISH. If in doubt, consult your documentation. ,J60 ESAC> *500 @ RECEIVE command help @ RECEIVE command: Syntax: RECEIVE [VME-filename] The RECEIVE command prepares VME Kermit for the arrival of a file from the micro Kermit. If a VME filename is specified, the file will be saved with this name. If no filename is specified, a filename will be sent by the micro Kermit and, if possible, the file will be saved with that name. After issuing the RECEIVE command, escape back to the micro Kermit and initiate the file transfer by entering a SEND command. ,J60 ESAC> *750 @ SEND command help @ SEND command: Syntax: SEND VME-filename [destination-filename] The VME file is sent to the micro Kermit. If a destination filename is included, the file will be stored by the micro with this name, otherwise the VME filename will be used. After issuing the SEND command escape back to the micro Kermit and prepare the micro for the arrival of the file by issuing a RECEIVE command. ,J60 ESAC> *1000 @ HELP command help @ HELP command: Syntax: HELP [command] [parameter(s)] The HELP command gives information for the specified command, or allows the user to request information via a menu. If a command is specified, it may be qualified by appending parameter names. ,J60 ESAC> *1250 @ EXIT command help @ EXIT command: Syntax: EXIT The EXIT command terminates the VME Kermit session, closes any logging files and returns the user to VME command level. ,J60 ESAC> *1500 @ SET command help @ OR <-1> THEN J1505, @ no parameter specified @ THEN J1520, THEN J1540, THEN J1560, THEN J1580, THEN J1600, THEN J1620, THEN J1640 DEFAULT J1504 @ invalid parameter @ ESAC > *1501 @ SET command help exit @ ,J1502 ESAC> *1502 @ more help prompt @ Any more help required? Select:- (0) No more help (1) More help for this command (2) More help for another command Enter choice (0 to 2): *1503 @ validate more help response @ THEN <>, <1> THEN J1505, <2> THEN J20 DEFAULT J1502 @ invalid response, reprompt @ ESAC > *1504 @ invalid SET parameter @ **** is not a SET parameter. *1505 @ SET command menu @ SET command: Syntax: SET parameter value The SET command establishes or modifies various parameters for file transfer or logging. The following parameters may be set: (1) DEBUG {FILE/PROTOCOL/PACKET/DEVICE/ALL} {ON/OFF} (2) DELAY seconds (3) PAUSE 10th-seconds (4) RETRY maximum-retries (5) FILE parameter value TYPE {EBCDIC/ASCII/BINARY} NAMING {UNTRANSLATED/NORMAL-FORM} OVERWRITE {ON/OFF} INCOMPLETE {DISCARD/KEEP} (6) SEND parameter value (7) RECEIVE parameter value START-OF-PACKET ctl-char PACKET-LENGTH number TIMEOUT number END-OF-LINE ctl-char PADDING number PAD-CHARACTER ctl-char QUOTE char EIGHTH-BIT-PREFIX char *1506 @ select SET parameter @ For further information enter choice (1 to 7) or 0 if no further information is required: *1507 @ validate selection @ THEN <>, <1> THEN J1520, <2> THEN J1540, <3> THEN J1560, <4> THEN J1580, <5> THEN J1600, <6> THEN J1620, <7> THEN J1640 DEFAULT J1508 @ invalid selection @ ESAC > *1508 @ invalid selection @ **** Invalid response, please re-select. *1520 @ SET DEBUG @ OR <-1> THEN J1525, @ no parameter specified @ THEN J1530, THEN J1531, THEN J1532, THEN J1533, THEN J1534 DEFAULT J1524 @ invalid parameter @ ESAC > *1521 @ SET DEBUG command help exit @ , J1522 ESAC> *1522 @ more help prompt @ Any more help required? Select:- (0) No more help (1) More help for this command (2) More help for another command Enter choice (0 to 2): *1523 @ validate more help response @ THEN <>, <1> THEN J1525, <2> THEN J20 DEFAULT J1522 @ invalid response, reprompt @ ESAC > *1524 @ invalid SET DEBUG parameter @ **** is not a SET DEBUG parameter. *1525 @ SET DEBUG command menu @ SET DEBUG: Syntax: SET DEBUG parameter option Sets the various debugging facilities on or off. The following parameters may be set: (1) FILE {ON/OFF} (2) PROTOCOL {ON/OFF} (3) PACKET {ON/OFF} (4) DEVICE {ON/OFF} (5) ALL {ON/OFF} *1526 @ select SET DEBUG parameter @ For further information enter choice (1 to 5) or 0 if no further information is required: *1527 @ validate selection @ THEN <>, <1> THEN J1530, <2> THEN J1531, <3> THEN J1532, <4> THEN J1533, <5> THEN J1534 DEFAULT J1528 @ invalid selection @ ESAC > *1528 @ invalid selection @ **** Invalid response, please re-select. *1530 @ SET DEBUG FILE @ SET DEBUG FILE: Syntax: SET DEBUG FILE option Turns file record tracing on or off. If option is ON then the contents of all file records read or written will be logged (in hex) to the job journal. The default is OFF. e.g. SET DEBUG FILE ON - turns on file record tracing. *1531 @ SET DEBUG PROTOCOL @ SET DEBUG PROTOCOL: Syntax: SET DEBUG PROTOCOL option Turns protocol state/event tracing on or off. If option is ON then the internal states and events of the protocol handler will be logged to the job journal. The default is OFF. e.g. SET DEBUG PROTOCOL ON - turns on protocol state/event tracing. *1532 @ SET DEBUG PACKET @ SET DEBUG PACKET: Syntax: SET DEBUG PACKET option Turns packet tracing on or off. If option is ON then the contents of all packets sent and received will be logged to the job journal. The default is OFF. e.g. SET DEBUG PACKET ON - turns on packet tracing. *1533 @ SET DEBUG DEVICE @ SET DEBUG DEVICE: Syntax: SET DEBUG DEVICE option Turns device tracing on or off. If option is ON then all the data sent and received over the terminal link will be logged (in hex) to the job journal. The default is OFF. e.g. SET DEBUG DEVICE ON - turns on device tracing. *1534 @ SET DEBUG ALL @ SET DEBUG ALL: Syntax: SET DEBUG ALL option Turns all tracing on or off. If option is ON then the contents of all file records read or written, the internal states and events of the protocol handler, the contents of all packets sent and received and all the data sent and received over the terminal link will be logged to the job journal. The default is OFF. e.g. SET DEBUG ALL ON - turns on all tracing. *1540 @ SET DELAY @ SET DELAY: Syntax: SET DELAY seconds Sets the length of delay before transmitting the first packet after a SEND command has been issued. The default delay is 30 seconds. The minimum delay that can be set is 5 seconds and the maximum is 300 seconds. Seconds may be expressed as a decimal value (e.g. 9) or as a hexadecimal value (e.g. X09). e.g. SET DELAY 15 - sets the delay period to 15 seconds. *1560 @ SET PAUSE @ SET PAUSE: Syntax: SET PAUSE 10ths-second Sets the length of time to pause between receiving a packet from the remote system and transmitting the next packet to it. The default pause is 0 tenths of a second. The maximum pause that can be set is 50 tenths of a second. 10ths-second may be expressed as a decimal value (e.g. 9) or as a hexadecimal value (e.g. X09). e.g. SET PAUSE 10 - sets the pause period to 10 tenths of a second. *1580 @ SET RETRY @ SET RETRY: Syntax: SET RETRY number Sets the maximum number of times to attempt to send or receive a packet before abandoning the transfer. The default retry is 4. The maximum retry that can be set is 10. Number may be expressed as a decimal value (e.g. 4) or as a hexadecimal value (e.g. X04). e.g. SET RETRY 8 - sets the retry limit to 8 retries. *1600 @ SET FILE @ OR <-1> THEN J1605, @ no parameter specified @ THEN J1610, THEN J1611, THEN J1612, THEN J1613 DEFAULT J1604 @ invalid parameter @ ESAC > *1601 @ SET FILE command help exit @ , J1602 ESAC> *1602 @ more help prompt @ Any more help required? Select:- (0) No more help (1) More help for this command (2) More help for another command Enter choice (0 to 2): *1603 @ validate more help response @ THEN <>, <1> THEN J1605, <2> THEN J20 DEFAULT J1602 @ invalid response, reprompt @ ESAC > *1604 @ invalid SET FILE parameter @ **** is not a SET FILE parameter. *1605 @ SET FILE command menu @ SET FILE: Syntax: SET FILE parameter option Sets the various file attributes. The following parameters may be set: (1) TYPE {EBCDIC/ASCII/BINARY} (2) NAMING {UNTRANSLATED/NORMAL-FORM} (3) OVERWRITE {ON/OFF} (4) INCOMPLETE {DISCARD/KEEP} *1606 @ select SET FILE parameter @ For further information enter choice (1 to 4) or 0 if no further information is required: *1607 @ validate selection @ THEN <>, <1> THEN J1610, <2> THEN J1611, <3> THEN J1612, <4> THEN J1613 DEFAULT J1608 @ invalid selection @ ESAC > *1608 @ invalid selection @ **** Invalid response, please re-select. *1610 @ SET FILE TYPE @ SET FILE TYPE: Syntax: SET FILE TYPE option Defines the type of file to be sent, or received. option may be one of: EBCDIC meaning that the VME file contains, or is to contain EBCDIC text and data conversion between EBCDIC and ASCII is required. ASCII meaning that the VME file contains, or is to contain ASCII text and no data conversion is required. BINARY meaning that the VME file contains, of is to contain binary data and no data conversion is required. Note in this case the record boundaries of the VME file are not significant to KERMIT. The default is EBCDIC. e.g. SET FILE TYPE BINARY - sets file transfer is to be binary. *1611 @ SET FILE NAMING @ SET FILE NAMING: Syntax: SET FILE NAMING option Defines how file names are to represented/interpretted. If option is NORMAL-FORM then the VME and remote file names will be normalised. If option is UNTRANSLATED then no file name normalisation will take place. The default is NORMAL-FORM. e.g. SET FILE NAMING UNTRANSLATED - turns off file name normalisation. *1612 @ SET FILE OVERWRITE @ SET FILE OVERWRITE: Syntax: SET FILE OVERWRITE option Defines the action to be taken when receiving a file and a VME file of the same name and generation number already exists. If option is ON then the file will be overwritten. If option is OFF then the file transfer will abandoned. The default is OFF. e.g. SET FILE OVERWRITE ON - incoming file will be overwritten if it already exists. *1613 @ SET FILE INCOMPLETE @ SET FILE INCOMPLETE: Syntax: SET FILE INCOMPLETE option Defines the action to be taken when receiving a file and the file transfer is abandoned. If option is KEEP then the VME file will be saved. If option is DISCARD then the VME file will not be saved. e.g. SET FILE INCOMPLETE KEEP - file to be saved if transfer abandoned. *1620 @ SET SEND @ *1640 @ SET RECEIVE @ *1650 @ SET SEND/RECEIVE @ OR <-1> THEN J1655, @ no parameter specified @ THEN J1660, THEN J1661, THEN J1662, THEN J1663, THEN J1664, THEN J1665, THEN J1666, THEN J1667 DEFAULT J1654 @ invalid parameter @ ESAC > *1651 @ SET SEND/RECEIVE command help exit @ , J1652 ESAC> *1652 @ more help prompt @ Any more help required? Select:- (0) No more help (1) More help for this command (2) More help for another command Enter choice (0 to 2): *1653 @ validate more help response @ THEN <>, <1> THEN J1655, <2> THEN J20 DEFAULT J1652 @ invalid response, reprompt @ ESAC > *1654 @ invalid SET SEND/RECEIVE parameter @ **** is not a SET SEND/RECEIVE parameter. *1655 @ SET SEND/RECEIVE command menu @ SET SEND/RECEIVE: Syntax: SET {SEND/RECEIVE} parameter option Sets the various configuration parameters to allow the tailoring of dissimilar systems to accomodate the peculiarities of the communication path. Note a number of the configuration parameters may be modified during the exchange of S or I packets and the acknowledgements to those packets. The following parameters may be set: (1) START-OF-PACKET ctl_char (2) PACKET-LENGTH number (3) TIMEOUT seconds (4) END-OF-LINE ctl-char (5) PADDING number (6) PAD-CHARACTER ctl-char (7) QUOTE char (8) EIGHTH-BIT-PREFIX char *1656 @ select SET SEND/RECEIVE parameter @ For further information enter choice (1 to 8) or 0 if no further information is required: *1657 @ validate selection @ THEN <>, <1> THEN J1660, <2> THEN J1661, <3> THEN J1662, <4> THEN J1663, <5> THEN J1664, <6> THEN J1665, <7> THEN J1666, <8> THEN J1667 DEFAULT J1658 @ invalid selection @ ESAC > *1658 @ invalid selection @ **** Invalid response, please re-select. *1660 @ SET SEND/RECEIVE START-OF-PACKET @ SET SEND/RECEIVE START-OF-PACKET: Syntax: SET {SEND/RECEIVE} START-OF-PACKET ctl-char Sets the ASCII control character to be used as the start-of-packet marker. The default is Record Separator (decimal 30, hex 1E). 'Ctl-char' may be expressed as a decimal value (e.g. 30) or as a hexadecimal value (e.g. X1E). Note a number of control characters are not accepted by VME as valid start-of-packet markers. e.g. SET SEND START-OF-PACKET X1F - sets the start-of-packet marker for output packets to Unit Separator. *1661 @ SET SEND/RECEIVE PACKET-LENGTH @ SET SEND/RECEIVE PACKET-LENGTH: Syntax: SET {SEND/RECEIVE} PACKET-LENGTH number Sets the maximum length for a packet. The maximum packet-length plus the padding (if any) must not exceed the limits of the VME terminal description (normally 80 for output and 128 for input). The default packet-length is 80 characters. The minimum packet-length that can be set is 30 characters and the maximum is defined by the terminal description (normally 80 for output and 94 for input). 'Number' may be expressed as a decimal value (e.g. 80) or as a hexadecimal value (e.g. X50). e.g. SET RECEIVE PACKET-LENGTH 72 - sets the maximum packet-length of input packets to 72 characters. *1662 @ SET SEND/RECEIVE TIMEOUT @ SET SEND/RECEIVE TIMEOUT: Syntax: SET {SEND/RECEIVE} TIMEOUT seconds Sets the length of time to wait for a packet to arrive. The default is 0 seconds i.e. indefinite wait. The maximum timeout that can be set is 94 seconds. 'Seconds' may be expressed as a decimal value (e.g. 20) or as a hexadecimal value (e.g. X14). e.g. SET RECEIVE TIMEOUT 20 - sets the timeout value for input packets to 20 seconds. *1663 @ SET SEND/RECEIVE END-OF-LINE @ SET SEND/RECEIVE END-OF-LINE: Syntax: SET {SEND/RECEIVE} END-OF-LINE ctl-char Sets the ASCII control character to be used as the end of packet terminator. The default is Carriage Return (decimal 13, hex 0D). 'Ctl-char' may be expressed as a decimal value (e.g. 13) or as a hexadecimal value (e.g. X0D). Note a number of control characters are not accepted by VME as valid end-of-line terminators. e.g. SET RECEIVE END-OF-LINE X09 - sets the input packet end-of-line terminator to Tab. *1664 @ SET SEND/RECEIVE PADDING @ SET SEND/RECEIVE PADDING: Syntax: SET {SEND/RECEIVE} PADDING number Sets the number of padding characters to be sent before each packet. The padding plus the maximum packet length must not exceed the limits of the VME terminal description (normally 80 for output and 128 for input). The default padding is 0 characters i.e. no padding. The maximum padding that can be set is defined by the VME terminal description. e.g. SET SEND PADDING 4 - sets the padding for output packets to 4 pad characters. *1665 @ SET SEND/RECEIVE PAD-CHARACTER @ SET SEND/RECEIVE PAD-CHARACTER: Syntax: SET {SEND/RECEIVE} PAD-CHARACTER ctl-char Sets the ASCII control character to be used as a pad character to be sent before each packet. The default is Null (decimal 0, hex 00). 'Ctl-char' may be expressed as a decimal value (e.g. 0) or as a hexadecimal value (e.g X00). Note a number of the control characters are not accepted by VME as valid pad characters. e.g. SET SEND PAD-CHARACTER 7 - sets the output packet pad character to Bell. *1666 @ SET SEND/RECEIVE QUOTE @ SET SEND/RECEIVE QUOTE: Syntax: SET {SEND/RECEIVE} QUOTE char Sets the printable ASCII character to be used for control character prefixing. It may be any printable character but it must be different from the eighth-bit-prefix character. The default value is Hash (#) (decimal 35, hex 23). 'Char' may be expressed as an ASCII character (e.g. #), as a decimal value (e.g. 35) or as a hexadecimal value (e.g. X23). e.g. SET SEND QUOTE ? - sets the output packet quote character to question mark. *1667 @ SET SEND/RECEIVE EIGHTH-BIT-PREFIX @ SET SEND/RECEIVE EIGHTH-BIT-PREFIX: Syntax: SET {SEND/RECEIVE} EIGHTH-BIT-PREFIX char Sets the printable ASCII character to be used for eighth bit prefixing. It may be any printable character in the range ASCII 32 to 62 or ASCII 96 TO 126 but it must be different from the control character prefix. The default value is Ampersand (&) (decimal 38, hex 26). 'Char' may be expressed as an ASCII character (e.g. &), as a decimal value (e.g. 38) or as a hexadecimal value (e.g. X26). e.g. SET SEND EIGHTH-BIT-PREFIX ! - sets the output packet eighth-bit-prefix character to exclamation mark. *1750 @ SHOW command help @ SHOW command: Syntax: SHOW Displays the current values of SET parameters, capabilities etc. ,J60 ESAC> *2000 @ STATISTICS command help @ STATISTICS command: Syntax: STATISTICS Displays statistical information about the most recent file transfer. ,J60 ESAC> *9000 @ START-OF-PACKET info @ VME I/0 cannot handle the standard Kermit START-OF-PACKET character Hex 01 (decimal 1) so initially the VME Kermit START-OF-PACKET character is set to Hex 1E (decimal 30). For a Kermit file transfer to work, the START-OF-PACKET character on the micro Kermit must be set to correspond to the VME Kermit START-OF-PACKET character. Consult the documentation for the micro Kermit to find out how to change the START-OF-PACKET character on the micro. If the VME Kermit START-OF-PACKET character isn't suitable for the micro Kermit then the START-OF-PACKET character should be altered on BOTH Kermits. Appendix 2 of the VME KERMIT User Guide lists the characters that VME I/O can handle. To change the START-OF-PACKET character on VME Kermit use the commands SET RECEIVE START-OF-PACKET and SET SEND START-OF-PACKET. HELP is available for these commands. If you attempt to alter the START-OF-PACKET character to an unacceptable character you will be notified. *END $$$$ KMT_SP_MTM *@ VME KERMIT SUPPORT PROCEDURE MESSAGE TEXT MODULE @ *@ ************************************************ @ *CREATE(KMTSPMTM) *PROC(KMTSPMTM) *VERSION(101) *PARAMS(EXP&ICL) *LINESPLIT(SPACE) *@ MESSAGES MESSAGE TEXTS @ *@ ********************** @ *@ GENERAL MESSAGES @ *@ **************** @ *1 @ KMT_VERSION_NUMBER @ SWURCC VME KERMIT VERSION *2 @ KMT_SWURCC_BANNER @ South West Universities Regional Computer Centre, Claverton Down, Bath BA2 7AY, U.K. *3 @ NON-STANDARD MARK CHARACTER @ The VME Kermit START-OF-PACKET character is Hex 1E (decimal 30). Please set the START-OF-PACKET character on your micro to correspond. Type: HELP START-OF-PACKET for further details. *@ SUPPORT PROCEDURES MESSAGES @ *@ *************************** @ *50 @ KMT_SP_TRACE_MSG @ DEFAULT <> ESAC> *@ ERROR HANDLER MESSAGES @ *@ ********************** @ *@ DEVICE HANDLER MESSAGES @ *@ *********************** @ *150 @ KMT_DH_DATA_IN_MSG @ KMT_DH_DATA_IN :- *151 @ KMT_DH_DATA_OUT_MSG @ KMT_DH_DATA_OUT :- *152 @ KMT_DH_EVENT_MSG @ KMT_DH_EVENT :- *@ FILE HANDLER MESSAGES @ *@ ********************* @ *200 @ KMT_FH_RECORD_IN_MSG @ KMT_FH_RECORD_IN :- *201 @ KMT_FH_RECORD_OUT_MSG @ KMT_FH_RECORD_OUT :- *@ PACKET PROCESSOR MESSAGES @ *@ ************************* *250 @ KMT_PP_TRACE_MESSAGE @ MARK = X"" LEN = SEQ = TYPE = , , , , , , , , , , , , DEFAULT ESAC> DATA = X"" CHECKSUM = X"" *251 @ KMT_PP_PACKET_IN_MSG @ KMT_PP_PACKET_IN :- *252 @ KMT_PP_PACKET_OUT_MSG @ KMT_PP_PACKET_OUT :- *253 @ KMT_PP_PACKET_DATA_IN_MSG @ KMT_PP_PACKET_DATA_IN *254 @ KMT_PP_PACKET_DATA_OUT_MSG @ KMT_PP_PACKET_DATA_OUT *255 @ EBCDIC DATA @ (EBCDIC) :- *256 @ ASCII DATA @ (ASCII) :- *257 @ BINARY DATA @ (BINARY) :- X"" *258 @ KMT_PP_PARAM_OUT_MSG @ KMT_PP_PARAM_OUT :- *259 @ KMT_PP_PARAM_IN_MSG @ KMT_PP_PARAM_IN :- *260 @ NO PARAMATERS! @ NONE! *261 @ KMT_PP_PARAMS @ MAXL = *262 TIME = *263 NPAD = *264 PADC = X"" *265 EOL = X"" *266 QCTL = X"" *267 QBIN = X"" *268 CHKT = "" *269 REPT = X"" *270 CAPAS = X"" *@ PROTOCOL HANDLER MESSAGES @ *@ ************************* *300 @ KMT_PH_STATES_MSG @ KMT_PH_STATES :- *301 @ KMT_PH_TRACE_MESSAGE @ STATE = (, , , , , , , , DEFAULT ESAC>), EVENT = (, , , , , , , , , , , , , , DEFAULT ESAC>) *@ COMMAND AND PARAMETER CHECKING @ *5000 @ check Kermit initial mode @ THEN HALT 0, THEN HALT 1, THEN HALT 2, THEN HALT 3 DEFAULT HALT 4 @ invalid mode @ ESAC > *5010 @ check Kermit command @ THEN HALT 0, THEN HALT 1, THEN HALT 2, THEN HALT 3, THEN HALT 4, THEN HALT 5, THEN HALT 6, THEN HALT 7 DEFAULT HALT 8 @ invalid command @ ESAC > *5100 @ SET command: check for SEND or RECEIVE option @ THEN HALT 0, THEN HALT 1 DEFAULT HALT -1 @ not present - ok though @ ESAC > *5110 @ check SET parameter @ THEN HALT 0, THEN HALT 1, THEN HALT 2, THEN HALT 3, THEN HALT 4 DEFAULT HALT 920 @ invalid parameter @ ESAC > *5120 @ check parameter following SEND or RECEIVE option @ THEN HALT 0, THEN HALT 1, THEN HALT 2, THEN HALT 3, THEN HALT 4, THEN HALT 5, THEN HALT 6, THEN HALT 7 DEFAULT HALT 921 @ invalid parameter @ ESAC > *5130 @ check DEBUG option @ THEN HALT 0, THEN HALT 1, THEN HALT 2, THEN HALT 3, THEN HALT 4 DEFAULT HALT 921 @ invalid DEBUG parameter @ ESAC > *5140 @ check FILE option @ THEN CASE P4 STARTS THEN HALT 0, THEN HALT 1, THEN HALT 2 DEFAULT HALT 931 ESAC, THEN CASE P4 STARTS THEN HALT 3, THEN HALT 4 DEFAULT HALT 931 ESAC, THEN CASE P4 STARTS THEN HALT 5, THEN HALT 6 DEFAULT HALT 931 ESAC, THEN CASE P4 STARTS THEN HALT 7, THEN HALT 8 DEFAULT HALT 931 ESAC DEFAULT HALT 921 @ invalid SET FILE argument @ ESAC > *5150 @ check OFF/ON option @ THEN HALT 0, THEN HALT 1 DEFAULT HALT 931 ESAC > *@ RESULTCODES MESSAGE TEXTS @ *@ ************************* @ *@ GENERAL RESULTCODES @ *@ ******************* @ *@ SUPPORT PROCEDURES RESULTCODES @ *@ ****************************** @ *80050 @ KMT_SP_NOT_HEX @ NON-HEXADECIMAL CHARACTERS FOUND IN STRING *80051 @ KMT_SP_STRING_TOO_BIG @ KMT_SP_STRING_TOO_BIG *@ ERROR HANDLER RESULTCODES @ *@ ************************* @ *80100 @ KMT_EH_ERROR_MSG @ *80101 @ KMT_EH_SOFTWARE_ERROR @ AN UNRECOVERABLE SOFTWARE ERROR HAS OCCURED *80102 @ KMT_EH_ICL_RESULT @ <>**** RC = RETURNED FROM PROCEDURE , <> DEFAULT <> ESAC> *@ DEVICE HANDLER RESULTCODES @ *@ ************************** @ *80150 @ KMT_DH_UNEXPECTED_BREAK_IN @ <>**** UNEXPECTED BREAK_IN EVENT **** *80151 @ KMT_DH_UNEXPECTED_EVENT @ <>**** UNEXPECTED EVENT **** *80152 @ KMT_DH_DATA_AVAILABLE @ KMT_DH_DATA_AVAILABLE *80153 @ KMT_DH_QUEUE_EMPTY @ KMT_DH_QUEUE_EMPTY *@ FILE HANDLER RESULTCODES @ *@ ************************ @ *80200 @ KMT_FH_RECORD_TOO_BIG @ <>**** MAXIMUM RECORD SIZE EXCEEDED, SIZE = , MAX SIZE = *@ PACKET PROCESSOR RESULTCODES @ *@ **************************** @ *80250 @ KMT_PP_NO_INPUT_PACKET @ KMT_PP_NO_INPUT_PACKET *80251 @ KMT_PP_UNSUPPORTED_PACKET_TYPE @ KMT_PP_UNSUPPORTED_PACKET_TYPE *80252 @ KMT_PP_INVALID_PACKET_TYPE @ KMT_PP_INVALID_PACKET_TYPE *80253 @ KMT_PP_INVALID_CHACKSUM @ KMT_PP_INVALID_CHECKSUM *80254 @ KMT_PP_INVALID_PACKET_LENGTH @ KMT_PP_INVALID_PACKET_LENGTH *80255 @ KMT_PP_RECORD_TOO_BIG @ <>**** MAXIMUM RECORD SIZE EXCEEDED, MAX SIZE = *80256 @ KMT_PP_STRING_TOO_BIG @ <>**** MAXIMUM MESSAGE SIZE EXCEEDED, SIZE = , MAX SIZE = *80257 @ KMT_PP_INVALID_CONFIG_PARAM @ INVALID CONFIGURATION PARAMETER ,<"NPAD">,<"PADC">,<"EOL">,<"QCTL">,<"QBIN">,<> ESAC>, VALUE = X"" THEN JP4 DEFAULT <> ESAC> *80258 @ KMT_PP_QBIN_AND_QCTL_EQUAL @ THE CONTROL-QUOTE AND EIGHTH-BIT-PREFIX CHARACTERS ARE EQUAL QBIN = X"", REMOTE QCTL = X"", LOCAL QCTL = X"" *80259 @ KMT_PP_QCTL_WARNING @ <>**** WARNING THE REMOTE QCTL CHARACTER X"" WILL RESULT IN THE CORRUPTION OF ANY X"" CHARACTERS TO X"" *80260 @ KMT_PP_QBIN_REJECTED @ THE EIGHTH-BIT PREFIXING HAS BEEN REJECTED BY THE REMOTE SYSTEM *80270 @ INVALID CONFIG PARAM REASONS@ (less than minimum packet length) *80271 (too many PAD characters requested) *80272 (not a control character) *80273 (not a printable character) *80274 (character not acceptable for VME I/O) *80275 (not a valid character) *80276 (same as START-OF-PACKET character) *80277 (same as END-OF-LINE character) *@ VME COMMAND ERRORS @ *85000 @ filenames not reqd @ **** File names not required with option. *85001 @ rem_file not reqd for Receive @ **** Remote filename not required with Receive option. *85010 @ vme_file mandatory for Send @ **** Filename must be specified with Send option. *85020 @ invalid option @ **** is not a valid VME Kermit option. *85030 @ terminated with fatal error @ **** VME Kermit terminated due to fatal error. *85031 @ logging out vm on exit @ Logging out.....! *85032 @ terminate with a new line @ *@ USER INTERFACE (KMT_UI) MESSAGES @ *85820 TRANSFER STATISTICS Packets in Packets out Retries Timeouts Records read Records written *85821 GENERAL PARAMETERS Send delay (secs) TX pause (10th sec) Maximum retries *85822 RECEIVE PARAMETERS *85823 SEND PARAMETERS *85824 Packet start XEnd of line X Packet length Timeout (secs) Padding Pad character X Quote character 8th bit prefix *85825 FILE PARAMETERS File type ,,, ESAC> Overwrite option THEN , <2> THEN DEFAULT ESAC,HALT -1> Incomplete , ESAC> Naming , ESAC,HALT -1> *85826 TERMINAL PARAMETERS Input length Output length *85827 DEBUGGING PARAMETERS File , ESAC> Protocol , ESAC,HALT -1> Packet , ESAC> Device , ESAC,HALT -1> *@ USER INTERFACE (KMT_UI) ERROR MESSAGES @ *85910 @ invalid command @ **** is not a valid VME Kermit command. *85920 @ invalid parameter P2 @ **** is not a valid command parameter. *85921 @ invalid parameter P3 @ **** is not a valid command parameter. *85930 @ invalid option P3 @ **** is not a valid command option. *85931 @ invalid option P4 @ **** is not a valid option. *85932 @ command parameter missing @ **** Command parameter missing. *85933 @ QUOTE and EIGHTH-BIT-PREFIX characters equal @ **** QUOTE and EIGHTH-BIT-PREFIX characters equal. *85934 @ Padding and packet length combined exceeds device length @ **** Padding plus packet length exceeds the device line length. *85935 @ START-OF-PACKET/END-OF-LINE/PADC not a control character @ **** parameter must be in range 0 - 31 or 127. *85936 @ parameter not acceptable for VME I/O @ **** parameter not acceptable for VME I/O. *85937 @ conflict with another character @ **** parameter conflicts with ,,,<> ESAC> character. *@ PROTOCOL HANDLER MESSAGES @ *87000 @ transfer cancelled by remote Kermit @ File transfer cancelled by remote Kermit. *87001 @ filename used by remote Kermit for sent file @ File sent as to remote Kermit. *87002 @ filename used by local Kermit for receive file @ File stored as on VME Kermit. *87010 @ error packet received, log details @ Remote Kermit error: *@ PROTOCOL HANDLER ERRORS @ *89000 @ unexpected pkt_no @ Unexpected packet number. *89001 @ unexpected pkt_type @ Unexpected packet type. *89010 @ Generic command failed @ Generic command "" failed. *89011 @ Generic command not implemented/recognised @ Generic command "" not implemented. *89020 @ Kermit command failed in Server mode @ Kermit command "" failed in Server mode. *89021 @ Kermit command not implemented in Server mode @ Kermit command "" not implemented in Server mode. *89022 @ No command in Kermit command packet @ No command found in Kermit command packet. *89030 @ No filename in Rec_Init pkt @ No filename in Receive Init packet. *89031 @ No filename in File_Hdr pkt @ No filename in File Header packet. *89040 @ Unable to open Rec file @ Unable to open Receive file. *89041 @ Unable to open Send file @ Unable to open Send file. *89042 @ Unable to close Rec file @ Unable to close file received. *89043 @ Unable to close Send file @ Unable to close Send file. *89044 @ Unable to save Rec file @ Unable to save file received. *89046 @ error writing to file @ Unable to write data to file. *89047 @ error reading from file @ Unable to read data from file. *89050 @ Retry count exceeded max_try. Maximum retries exceeded. *89060 @ Fatal error in Get_Packet @ Fatal I/O error: unable to read packet. *89061 @ Fatal error in Send_Packet @ Fatal I/O error: unable to send packet. *89070 @ their parameters unacceptable @ Initial parameters unacceptable. *END @ KMT_SP_MTUP_MODULE @