; M4RMT/ASM ; REMOTE KERMIT COMMAND REMOTE LD A,CMKEY LD DE,RMTTAB CALL COMND JP KERMT2 LD C,A ;SAVE THE TYPE CALL NEWLIN LD B,0 LD HL,RMTJTB ;GET THE JUMP TABLE ADD HL,BC ;COMPUTE THE ADDRESS LD A,'G' LD (PKTTYPE),A ;Set to generic packet JP (HL) ; REMOTE COMMAND JUMP TABLE RMTJTB JP RMTCWD ;CHANGE WORKING DIRECTORIES JP RMTDEL ;DELETE A FILE JP RMTDIR ;DISPLAY A DIRECTORY JP RMTDSK ;DO A REMOTE DISK ALLOCATION JP RMTHLP ;GET REMOTE HELP JP RMTHST ;DO REMOTE HOST COMMAND JP RMTKER ;DO REMOTE KERMIT COMMAND JP RMTWHO ;RUN A REMOTE PROGRAM JP RMTREN ;SEND DATA TO A REMOTE PROGRAM JP RMTTYPE ;DISPLAY A REMOTE FILE JP RMTCOPY ;Copy a file JP RMTMSG ;Send a message JP RMTSET ;Set a variable JP RMTQUERY ;Query a variable JP RMTCLOSE ;Close the log JP RMTSEND ;Send the log JP RMTSTART ;Start logging JP RMTSTOP ;Stop logging JP RMTLOGIN ;Login to dedicated server JP RMTPRG ;Remote program manipulation JP RMTSRV ;Remote server status query ; ; DO A GENERIC REMOTE COMMAND ; GENCMD LD DE,RMTDATA ;Set the initial destination LD B,0 ;Set the initial counters LD (GENTYPE),A ;Save the type IFA 'J',GENCMD1 ;Jump if journaling IFANOT 'V',GENCMD2 ;Jump if not variable GENCMD1 LD A,C ;Get the second attribute LD (DE),A ;Store it INC DE ;Point ahead INC B ;Plus one for the extra attribute GENCMD2 LD C,0 ;Reset the beginning field length GENCMD3 LD (INITRMT),DE ;Save the values LD (INITCNT),BC CALL ENCFLDS ;Get the input fields GENCMD5 LD A,'1' ;SET CURRENT CHECK SUM LD (CURCHK),A XOR A ;Set the packet number to zero LD (ARGBLK),A NSTATE 'I' ;Set the state to I-initiate CALL INIT ;Initialize buffers LD HL,0 ;Set packet count to zero LD (NUMPKT),HL LD (NUMRTR),HL ;Reset number of retries XOR A ;Set mode to display on screen LD (DISFLG),A LD (PKTNUM),A ;Zero current packet number LD (NUMTRY),A ;Zero retries for current packet LD (CZSEEN),A CALL CLRPRT CALL PROTO JP KERMIT ; ; State G of the protocol. Build a G or C packet, and send it ; DOGEN EQU $ CALL CHKTRYS ;Check the retry count LD A,(PKTNUM) ;Set the packet number to current LD (ARGBLK),A LD HL,FILBUF ;Transfer data to the buffer LD DE,DATA ;Get the DATA area LD A,(PKTTYPE) ;Get the requested type, 'G' or 'C' IFA 'C',DOGEN6 ;If COMMAND then jump INC DE ;Point to data+1 if not remote host DOGEN6 LD A,(GENLEN) ;Get the length IFZ DOGEN1 ;Jump if no length LD C,A ;Make BC the count LD B,0 LDIR ;Move the bytes DOGEN1 LD C,A ;Store the length LD A,(PKTTYPE) ;Check the type again IFA 'C',DOGEN7 ;If COMMAND then jump LD A,(GENTYPE) ;Get the GENERIC type LD (DATA),A ;Store it INC C ;Add one to DATA length LD A,'G' ;Send a generic packet DOGEN7 PUSH AF ;Save the packet type LD A,C ;Get the length of DATA LD (ARGBLK+1),A ;Store it LD A,'1' ;Always 1 character checksum LD (CURCHK),A LD A,(CHKTYP) ;Get the desired checksum type LD (INICHK),A ;Save it for later POP AF ;Get the packet type back CALL SPACK ;Send the packet JP ABORT ;Abort on an error RPACKET ;Receive a packet IFANOT 'S',DOGEN2 ;Skip if not send_init LD A,(ARGBLK+1) ;Get the length LD HL,DATA ;Get the DATA area CALL SPAR ;Get parameters from packet LD HL,DATA ;Get the DATA area CALL RPAR ;Put our capabilities in LD (ARGBLK+1),A ;Store the length that is returned SPACKET 'Y' ;Send ACK with parameters LD A,(INICHK) ;Get the requested checksum type LD (CURCHK),A ;Store it as current NSTATE 'f' ;Set state to file receive RET ;Return to protocol switch DOGEN2 IFANOT 'X',DOGEN3 ;X packet? Jump if not CALL SETUPDIS ;Set up for terminal display CALL PRTPKTOUT ;Print the packet contents CALL DOINC ;Increment everything LD (ARGBLK+1),A ;A is zero, so use for zero length SPACKET 'Y' ;Send ACK NSTATE 'd' ;Set state to receive DATA RET ; DOGEN3 IFANOT 'Y',DOGEN4 ;Jump if not ACK CALL NEWLIN ;Get a new line for data CALL PRTPKTOUT ;Print the packets contents on screen NSTATE 'C' ;Set state to complete RET ;Return to proto switch ; DOGEN4 CP 'N' ;Was it NAK? RET Z ;If so, stay in this state IFANOT 'E',DOGEN5 ;If not Error packet, then go CALL ERROR ;Print error message CALL NEWLIN ;Get a new line JP KERMIT ;Get a new command ; DOGEN5 STROUT UNKNOWN ;Print unknown packet type message XOR A LD (ARGBLK+1),A ;Set DATA length to zero SPACKET 'E' ;Send an error packet JP KERMIT ;Get a new command ; ; Do remote directory ; RMTDIR EQU $ GENCASE 'D',1 ; ; Remote delete file ; RMTDEL EQU $ GENCASE 'E',1 ; ; Remote disk utilization ; RMTDSK EQU $ GENCASE 'U',1 ; ; Remote Help ; RMTHLP EQU $ GENCASE 'H',1 ; ; Remote Program control ; RMTPRG EQU $ GENCASE 'P',2 ; ; Remote Kermit Command ; RMTKER EQU $ GENCASE 'P',1 ; ; Remote type command ; RMTTYPE EQU $ GENCASE 'T',1 ; ; Remote who command ; RMTWHO EQU $ GENCASE 'W',2 ; ; Remote change directory ; RMTCWD EQU $ GENCASE 'C',2 ; ; Remote rename a file ; RMTREN EQU $ GENCASE 'R',2 ; ; Remote copy a file ; RMTCOPY EQU $ GENCASE 'K',2 ; ; Remote send a message ; RMTMSG EQU $ GENCASE 'M',2 ; ; Remote set a variable ; RMTSET EQU $ LD C,'S' GENCASE 'V',2 ; ; Remote query a variable ; RMTQUERY EQU $ LD C,'Q' GENCASE 'V',2 ; ; Remote close the log file ; RMTCLOSE EQU $ LD C,'c' GENCASE 'J',1 ; ; Remote send log file ; RMTSEND EQU $ LD C,'s' GENCASE 'J',1 ; ; Remote start logging ; RMTSTART EQU $ LD C,'+' GENCASE 'J',1 ; ; Remote stop logging ; RMTSTOP EQU $ LD C,'-' GENCASE 'J',1 ; ; Remote login ; RMTLOGIN EQU $ GENCASE 'l',3 ; ; Remote server status query ; RMTSRV EQU $ GENCASE 'Q',1 ; ; Remote host command ; RMTHST EQU $ LD DE,FILBUF LD A,CMTXT CALL COMND JP KERMT2 LD (TEMP4),A LD A,CMCFM CALL COMND JP KERMT3 LD A,(TEMP4) LD (GENLEN),A LD C,A LD B,0 LD HL,FILBUF ADD HL,BC LD (HL),0 LD A,1 LD (FLDLEN),A LD A,'C' LD (PKTTYPE),A JP GENCMD5 ; ; Get users response, and put it into the buffer ; ENCFLDS LD A,CMTXT LD DE,DATA ;Get the text CALL COMND JP KERMT2 CALL ENCOLEN ;Length encode each argument JP GETFIELD1 ;On error jump LD HL,RMTDATA ;Get the input buffer CALL ENCSTR ;Encode the contents LD A,(SIZE) ;Get the length LD (GENLEN),A ;Save it for later RET ;Return ; GETFIELD1 EQU $ ;Bad string found in encodelen STROUT TOOLONG ;Print string too long message JP KERMIT ;Abort completely ; ; Protocol switch code ; PROTO EQU $ LD A,(STATE) SWITCH 'D',SDATA ;Send data SWITCH 'F',SFILE ;Send file SWITCH 'T',SNDTRAN ;Transition from 'F' to 'D' SWITCH 'Z',SEOF ;Send EOF SWITCH 'S',SINIT ;Send init SWITCH 'B',SEOT ;End of transmittion SWITCH 'C',COMP ;Completed SWITCH 'A',SABORT ;Abort SWITCH 'd',RDATA ;Receive data SWITCH 'f',RFILE ;Receive file SWITCH 't',RECTRAN ;Transition from 'f' to 'd' SWITCH 'R',RINIT ;Receive init SWITCH 'r',RINITF ;Receive init with filename (GET command) SWITCH 'G',DOGEN ;Generic server command SWITCH 'I',IINIT ;Generic init packet CALL SABORT ;Bad protocol state JP KERMIT ;Abort ; ; SEND I-INITIATE ; IINIT CALL CHKTRYS ;Check retry threshold LD A,'1' ;RESET TO USE SINGLE CHARACTER CHECKSUM LD (CURCHK),A ;FOR STARTUP LD A,(CHKTYP) ;GET OUR DESIRED BLOCK CHECK TYPE LD (INICHK),A ;Store it as the initial value LD HL,DATA ;GET A POINTER TO OUR DATA BLOCK. CALL RPAR ;SET UP THE PARAMETER INFORMATION. LD (ARGBLK+1),A ;SAVE THE NUMBER OF ARGUMENTS. LD A,(PKTNUM) ;GET THE PACKET NUMBER. LD (ARGBLK),A SPACKET 'I' ;Send the I packet RPACKET ;Get the answer packet CP 'Y' ;Is it an ACK? JP NZ,IINIT3 ;IF NOT TRY NEXT. CALL CHKBLK RET NZ ;IF NOT TRY AGAIN. CALL DOINC LD A,(ARGBLK+1) ;GET THE NUMBER OF PIECES OF DATA. LD HL,DATA ;POINTER TO THE DATA. CALL SPAR ;READ IN THE DATA. LD A,(INICHK) ;GET THE AGREED UPON BLOCK-CHECK-TYPE LD (CURCHK),A ;STORE AS TYPE TO USE FOR PACKETS NOW NSTATE 'G' RET IINIT3 IFANOT 'N',IINIT4 ;NAK? CALL UPDRTR ;UPDATE THE NUMBER OF RETRIES. RET IINIT4 CP 'E' ;IS IT AN ERROR PACKET. JP NZ,ABORT ;JUMP IF NOT LD A,80 ;SET UP ALL DEFAULT PARAMETERS LD (SPSIZ),A XOR A LD (SPAD),A LD (SPADCH),A LD A,13 LD (SEOL),A LD A,'1' LD (CURCHK),A LD A,'#' LD (SQUOTE),A NSTATE 'G' RET ; ; This routine encodes the length of the blank separated fields ; into a packet for the generic routines. If there are more ; blank separated fields than FLDLEN says there should be, the ; remaining fields are added to the end of the last field, ; separated by blanks. ; ENCOLEN LD HL,DATA ;Get the source LD DE,(INITRMT) ;Get the initial location LD BC,(INITCNT) ;Get the initial counters PUSH DE ;Save the store address for length PUSH BC INC DE ;Point to where the data goes LD A,(FLDLEN) ;Get the number of fields LD B,A ;Put it into the counter POP AF ;Get the initial length LD (FLDLEN),A ;Set the length to zero initially ENCLEN1 LD A,(HL) ;Get a character IFANOT 20H,ENCLEN4 ;Jump if not space ENCLEN2 INC HL ;Point to next character IFA (HL),ENCLEN2 ;Loop while we are looking at a space DJNZ ENCLEN3 ;See if we have done all fields INC B ;Reset the counter back to one if so LD (DE),A ;Store a space INC DE ;Point to next place to store at INC C ;Increment the field length JR ENCLEN1 ;Process next character ENCLEN3 LD A,C ;Get the field length TOCHAR ;Make it printable EX (SP),HL ;Get the store address for the length LD (HL),A ;Store the length byte POP HL ;Restore the old HL PUSH DE ;Save the new length byte address INC DE ;Point to the data store address LD C,0 ;Reset the count of characters LD A,(FLDLEN) ;Get the total length INC A ;Add one to the length LD (FLDLEN),A ;Store the new length JR NZ,ENCLEN1 ;Continue if OK POP DE ;Restore the stack RET ;Return error ENCLEN4 JR C,ENCLEN5 ;If this is a control character then stop INC C ;Correct for the comming decrement LDI ;Move one char, and increment counter INC C ;Plus one more for the length LD A,(FLDLEN) ;Get the length INC A ;Add one for current character LD (FLDLEN),A ;Store the new length JR NZ,ENCLEN1 ;Top of the loop if no overflow POP DE ;Restore the stack RET ;Return error ENCLEN5 POP HL ;Get the length address LD A,C ;Get the length TOCHAR ;Make it printable LD (HL),A ;Store this fields length XOR A ;Terminate the packet LD (DE),A LD A,(FLDLEN) ;Get the overall length LD (GENLEN),A ;Save it for later OR A ;Is it a null length string? JP Z,RSKP ;Return if it is INC A ;Add one to length for field length byte CP MAXPKT-4 ;Too big for packet? RET P ;Return error if string too long LD (GENLEN),A ;Save it JP RSKP ;Return to the caller ;end of file