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 @