; CPSREM.ASM
;       KERMIT - (Celtic for "FREE")
;
;       This is the CP/M-80 implementation of the Columbia University
;       KERMIT file transfer protocol.
;
;       Version 4.0
;
;       Copyright June 1981,1982,1983,1984
;       Columbia University
;
; Originally written by Bill Catchings of the Columbia University Center for
; Computing Activities, 612 W. 115th St., New York, NY 10025.
;
; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
; others. 
;
;       This file contains the (system-independent) routines that implement
;       the REMOTE commands of the KERMIT protocol.
;
; revision history:
;
;edit 13, 21-Mar-1991 by MF. Renamed REMOTE SET FILE COLLISION REPLACE to
;	REMOTE SET FILE COLLISION OVERWRITE and modified the corresponding
;	help text slightly.
;edit 12, 13-Feb-1991 by MF. Simplified code at "remcl0" to get REMOTE
;	command arguments by calling "cmgtch" in order to get command-line
;	characters directly. This means that command-line characters are
;	passed literally (except for prefixingand space-compression) to the
;	remote Kermit and that one need not send "?" or <esc> as "\"-prefixed
;	octal numbers in order to avoid immediate action by CP/M Kermit.
;edit 11, 30-Jan-1991 by MF. Corrected code to always require entry of at least
;	one argument in the REMOTE COPY, REMOTE DELETE (REMOTE ERASE),
;	REMOTE MESSAGE, REMOTE RENAME and REMOTE TYPE commands. This is
;	done by branching to KERMT3 (the "not confirmed" code) if the
;	first argument isn't given. This should correct a bug which occurred
;	in numerous places in which the character immediately following
;	that specifying the flavor of a Generic command was not defined if
;	the first of multiple (at least two) arguments was left blank but
;	subsequent arguments were not. This should correct a problem
;	encountered by Russell Lang of Monash University In Australia when
;	he did a REMOTE MESSAGE command with a blank first argument (the
;	user id) and a nonblank second argument (the message text) from
;	CP/M Kermit to Ms-Kermit in Server mode.
;edit 10, 14-Dec-1990 by MF.  Put "<<>>" around "x" or "F" packet replies
;	to REMOTE commands as in VMS Bliss Kermit and eliminate unnecessary
;	instruction before label remc2d.
;edit 9, 1-Nov-1990 by MF.  Changed REMOTE CWD to REMOTE CD in the quest for
;	uniformity of nomenclature (per request of FDC).
;edit 8, 29-Oct-1990 by MF.  Corrected Remote command code to properly
;	prefix control characters (repeat prefix (~) isn't done in CP/M
;	yet).
;edit 7, 17-Oct-1990 by MF.  Changed verb "REMOTE SEND-MESSAGE" to
;	"REMOTE MESSAGE" to conform with the nomenclature suggested in
;	Chapter 10 of the 6th edition of the Kermit Protocol Manual.
;edit 6, 10-Oct-1990 by MF.  Corrected Remote command code to
;	properly prefix the control-character prefix character and the
;	eighth-bit quotation prefix character.  Remote Set commands
;	now function correctly.
;	Also change the REMOTE SET FILE COLLISION ASK value to 5 per
;	Kermit Digest V12 #6 (though I still have no idea how the local
;	Kermit is supposed to answer).
;edit 5, 5-Oct-1990 by MF.  Coded many Remote Set commands.
;	The commands I have omitted deal with Attribute packets which
;	don't make much sense on a CP/M system.
;	Note also that for those Remote Set commands which take a
;	numeric argument, no range-checking is done here.
;	Also note that, for now, REMOTE SET FILE-COLLISION ASK is
;	equivalent to REMOTE SET FILE-COLLISION DISCARD because
;	(a) that's what the Kermit Digest indicated and (b) no mechanism
;	has been proposed for the Remote Kermit to query the Local Kermit.
;edit 4, 29-Sep-1990 by MF.  Corrected code to ignore error packets in
;	response to sending an "I" packet, per KPROTO.DOC
;edit 3, 9-Sep-1990 by MF.  Extensively revised this file to implement
;	Remote commands except for the following:
;	REMOTE JOURNAL, REMOTE MAIL, REMOTE PRINT, REMOTE PROGRAM,
;	REMOTE SET, REMOTE VARIABLE.
;edit 2 ... MF Dunno where edit 2 went (shown in Version string).
; edit 1: September 8th, 1987.  Created this file from bits of the two packet files.
;	The commands supported by this system are all the REMOTE commands,
;	to allow users to acces remote host systems via Kermit.  Added REMOTE
;	command table and REMOTE DIR command.
;
;
remver:	db	'CPSREM.ASM (13)  21-Mar-1991$'	; name, edit number, date

;
;  REMOTE command - quite similar to the SET command
remote:	call selmdm		;Select modem
	call	flsmdm		;Flush buffers
	call	selcon		;Back to keyboard
	lxi	d,remtab	; remote commands table
	lxi	h,remhlp	; remote help table
	call	keycmd		; get result
	xchg
	pchl		; and do it




; REMOTE command table.  Works the same way as every other table etc.
;
remtab:	db	19		; nineteen commands so far
	db	2,'CD$'
	dw	remcd		; remote cd command
	db	4,'COPY$'
	dw	remcpy		; remote copy command
	db	6,'DELETE$'
	dw	remdel		; remote delete command
	db	9,'DIRECTORY$'
		dw	remdir	; remote directory command
	db	10,'DISK-USAGE$'
	dw	remdsk		; remote disk-usage command
	db	5,'ERASE$'
	dw	remdel		; remote erase command (same as delete)
	db	6,'FINISH$'
		dw	finish	; same as finish
	db	4,'HELP$'
	dw	remhep		; remote help command
	db	4,'HOST$'
	dw	remhos		; remote host command
	db	6,'KERMIT$'
	dw	remker		; remote Kermit command
	db	5,'LOGIN$'
	dw	remlgi		; remote login
	db	6,'LOGOUT$'
		dw	logout	; same as logout
	db	7,'MESSAGE$'
	dw	remmsg		; remote message command
	db	6,'RENAME$'
	dw	remren		; remote rename
	db	3,'SET$'
	dw	remset		; remote set command
	db	5,'SPACE$'
	dw	remdsk		; remote space command (same as disk-usage)
	db	6,'STATUS$'
	dw	remsta		; remote status (of server) command
	db	4,'TYPE$'
	dw	remtyp		; remote type command
	db	3,'WHO$'
	dw	remwho		; remote who command

remhlp:	db	cr,lf,'CD - change default directory for remote server'
	db	' operations'
	db	cr,lf,'COPY - copy files on a remote system'
	db	cr,lf,'DELETE - delete files on a remote system'
	db	cr,lf,'DIRECTORY - list a directory on a remote system'
	db	cr,lf,'DISK-USAGE - show disk usage on a remote system'
	db	cr,lf,'FINISH - stop a remote server'
	db	cr,lf,'HELP - get help from a remote server'
	db	cr,lf,'HOST - execute a command on a remote system'
	db	cr,lf,'KERMIT - tell a remote server to execute a Kermit '
		db	'command'
	db	cr,lf,'LOGIN - send user-identification to a remote server'
	db	cr,lf,'LOGOUT -  stop and logout a remote server'
	db	cr,lf,'MESSAGE - send a message to a remote system user'
	db	cr,lf,'RENAME - rename files on a remote system'
	db	cr,lf,'SET - set remote server parameters'
	db	cr,lf,'SPACE - show disk-usage on a remote system'
	db	cr,lf,'STATUS - Get status of a remote server'
	db	cr,lf,'TYPE - type files on a remote system'
	db	cr,lf,'WHO - show current users on a remote system'
	db	'$'


;Description of remote commands

;
;  Packets start with an I packet in place of S/R packet.  An X
;	packet is the same as an F (filename) packet except the 'file'
;	is not applicable.  Copy X packet data field to display.  Set
;	options so that no data is written to disk during D packets. 
;	(REMTXT <> 0)
;
;Packets:
;	we	we	comments
;	send	receive
;	I
;		ACK
;	Command packet
;		Ack or
;		Init
;	ACK
;		X	Dummy header.
;	ACK
;		D	listing from remote end
;	ACK		We got it
;	....
;	ACK		last packet received ok
;		Z
;	ACK
;		B
;	ACK		end of transaction.
;
;**Note** If the Remote system gives a simple ack to the command packet,
;that is, a "short reply" is given, the data, if any, in the packet
;is displayed and the transaction ends.  The outline shown above is for a
;"long reply".
;
; Remote commands
;
; Remote Copy - Copy file(s) on remote system
;
remcpy:	lxi	h,newfms	;Second argument prompt
	shld	rprmpt		;...
	mvi	a,'K'		;Generic type
remcp0:	sta	remdat		;into packet
	mvi	a,2		;Packet has at least two characters
	sta	rdl		;...
	mvi	a,'G'		;Generic command
	sta	rcom		;...
	lxi	d,remdat+2	;Point to data buffer
	call	remcli		;Get filespec (if any) from command line
	ora	a		;Anything typed?
	  jz	kermt3		;No, we must have an argument
	mov	b,a		;Save length
	adi	space		;Yes, make encoded field length
	sta	remdat+1		;and store in packet data area
	lda	rdl		;Get packet length so far
	add	b		;Count answer length
	sta	rdl		;and remember new packet size
	lhld	rprmpt		;Point to "new file" prompt
	xchg		;...
	shld	rptr		;Save data pointer
	call	prompt		;Prompt the user
	lhld	rptr		;Get data pointer again
	inx	h		;Skip encoded field-length
	xchg		;...
	call	remcli		;get user's answer
	lhld	rptr		;Restore pointer
	mov	c,a		;Save answer length
	adi	space		;Convert to encoded field length
	mov	m,a		;Put length in packet
	lda	rdl		;Get accumulated data length
	add	c		;plus data length
	adi	1		;plus field length character
	sta	rdl		;and remember it
	jmp	remcom		;and branch to common code
;
; Remote Cd - Change Directory
;
remcd:	lxi	h,pswdms	;Second argument prompt
	shld	rprmpt		;...
	mvi	a,'C'		;Generic cd
remcd0:	sta	remdat		;into packet
	mvi	a,1		;Packet is at least one character long
	sta	rdl		;...
	mvi	a,'G'		;Generic command
	sta	rcom		;...
	lxi	d,remdat+2	;Point to data buffer
	call	remcli		;Get filespec (if any) from command line
	mov	b,a		;Save answer length (may be zero)
	adi	space		;Make encoded field length
	sta	remdat+1		;and store in packet data area
	lda	rdl		;Get length so far
	add	b		;Count answer length
	adi	1		;and field length character
	sta	rdl		;and remember current packet-size
	lda	remdat		;Get generic packet flavor
	cpi	'C'		;Remote CD?
	jnz	remcd1		;No
	mov	a,b		;Get length of possible directory spec
	ora	a		;Did the user give a directory spec?
	jz	remcom		;No, we can process the command immediately
	mvi	a,0ffH		;Yes, password follows, make it not echo
	sta	cmqflg		;...
remcd1:	lhld	rprmpt		;Point to "password" prompt
	xchg		;...
	shld	rptr		;Save data pointer
	mvi	a,0ffH		;Allow blank password
	sta	cmbflg		;...
	call	prompt		;Prompt the user
	lhld	rptr		;Restore data pointer
	xchg		;...
	inx	d		;and increment it
	call	remcli		;Get user's answer
	ora	a		;Password given?
	  jz	remcom		;No, proceed with command
	mov	c,a		;Yes, save answer length
	adi	space		;Convert to encoded field length
	lhld	rptr		;Get data pointer
	mov	m,a		;Put length in packet
	lda	rdl		;Get accumulated data length
	adi	1		;Count encoded field length
	add	c		;plus data length
	sta	rdl		;and remember packet-size
	jmp	remcom		;Branch to common code
;
; Remote Delete (Erase) command
;
remdel:	mvi	a,'E'		;Delete (Erase) command
remdl0:	sta	remdat		;...
	mvi	a,1		;At least one character in packet
	sta	rdl		;...
	mvi	a,'G'		;Generic command
	sta	rcom		;...
	lxi	d,remdat+2	;Point to data field
	call	remcli		;Get filespec
	mov	b,a		;Save length
	lda	remdat		;Get packet type
	cpi	'E'		;If Generic Delete
	jz	remdl1		;We must have an argument
	cpi	'T'		;Ditto for Generic Type
	jz	remdl1		;...
	mov	a,b		;Else get back character count
	ora	a		;Answer typed?
	  jz	remcom		;No, process packet as is
remdl1:	mov	a,b		;Get character count again
	ora	a		;Anything typed?
	jz	kermt3		;No, we must have an argument (Delete/Type)
	adi	space		;Yes, encode field length
	sta	remdat+1		;and put in packet
	lda	rdl		;Get packet length so far
	add	b		;Count length of filespec
	adi	1		;Count field length character
	sta	rdl		;and store packet length
	jmp	remcom		;and do our stuff
;
; Remote Directory command
;
remdir:	mvi	a,'D'		;generic directory command
	jmp	remdl0		;Do common code
;
; Remote Disk-usage (Space) command
;
remdsk:	mvi	a,'U'		;Disk-usage generic command
	jmp	remdl0		;Do common code
;
; Remote Help command
;
remhep:	mvi	a,'H'		;generic help command
	jmp	remdl0		;Do common code
;
; Remote Host command
;
remhos:	mvi	a,'C'		;Remote Host command
remho0:	sta	rcom		;...
	xra	a		;Zero packet length
	sta	rdl		;...
	lxi	d,remdat		;Point to packet data buffer
	call	remcli		;Get host command
	ora	a		;Anything typed?
	jz	kermt3		;No, don't let the user get away with this
	sta	rdl		;Yes, store packet length
	jmp	remcom		;and do the command
;
; Remote Kermit command
;
remker:	mvi	a,'K'		;Remote Kermit command
	jmp	remho0		;Do common code
;
; Remote Login command
;
remlgi:	mvi	a,'G'		;Generic command
	sta	rcom		;...
	mvi	a,'I'		;Generic type
	sta	remdat		;into packet
	mvi	a,1		;At least one character in packet
	sta	rdl		;...
	lxi	d,remdat+2	;Point to data buffer
	call	remcli		;Get userid (if any) from command line
	ora	a		;Userid typed?
	  jz	remcom		;No, nothing more to do
	mov	b,a		;Yes, save length
	adi	space		;Make encoded field length
	sta	remdat+1		;and store in packet data area
	lda	rdl		;Get packet length
	add	b		;Count id length
	adi	1		;and field length character
	sta	rdl		;and remember accumulated length
	xchg		;Save data pointer
	shld	rptr		;...
	mvi	a,0ffH		;Allow blank answers
	sta	cmbflg		;...
	sta	cmqflg		;Passwords don't echo
	lxi	d,pswdms	;Point to "password" prompt
	call	prompt		;Prompt the user
	lhld	rptr		;Get data pointer
	xchg		;Put in DE
	inx	d		;Skip encoded field-length
	call	remcli		;Get password, if any
	ora	a		;Anything typed?
	  jz	remcom		;No, do command immediately
	mov	c,a		;Yes, save answer length
	adi	space		;Convert to encoded field length
	lhld	rptr		;Get pointer
	mov	m,a		;Put length in packet
	lda	rdl		;Get accumulated data length
	adi	1		;Count encoded field length
	add	c		;Count "password" field length
	sta	rdl		;and remember new packet length
	xchg		;Save data pointer
	shld	rptr		;...
	xra	a		;Allow echoing again for "account" field
	sta	cmqflg		;...
	lxi	d,acctms	;Point to "account" prompt
	call	prompt		;Prompt the user
	lhld	rptr		;Get data pointer
	xchg		;into DE
	inx	d		;Skip encoded field length
	call	remcli		;Get "account" field, if any
	ora	a		;Anything typed?
	  jz	remcom		;No, do the command now
	mov	c,a		;Yes, save length of answer
	adi	space		;Convert to encoded field length
	lhld	rptr		;Get data pointer
	mov	m,a		;Put length in packet
	lda	rdl		;Get accumulated data length
	adi	1		;Count encoded field length
	add	c		;plus "account" length
	sta	rdl		;and remember it
	jmp	remcom		;Branch to common code
;
; Remote Rename command
;
remren:	lxi	h,newfms	;Second argument prompt
	shld	rprmpt		;...
	mvi	a,'R'		;generic rename
	jmp	remcp0		;Do common code
;
; Remote Message command
;
remmsg:	lxi	h,msgms		;Second argument prompt
	shld	rprmpt		;...
	mvi	a,'M'		;generic message
	jmp	remcp0		;Do common code
;
;Remote Set command
;
remset:	mvi	a,6		;Packet data area has at least six chars
	sta	rdl		;...
	mvi	a,'S'		;Remote Set command
	sta	remdat		;...
	mvi	a,'G'		;It's a generic command
	sta	rcom		;...
	mvi	a,'#'		;Encoded field-length for SET type
	sta	remdat+1	;which is three chars long
	lxi	d,rmstab	;Point to Set command table
	lxi	h,rmshlp	;and the help table
	call	keycmd		;Find out which command is to be executed
	xchg		;Put dispatch address in HL
	pchl		;Go do the command
;
; Common code for Remote Set commands that take an argument
;
remscm:	lxi	d,remdat+6	;We get an argument from the user
	mvi	a,cmtxt		;...
	call	comnd		;...
	jmp	kermt3		;Couldn't get one.
	ora	a		;Did the user give one?
	jz	kermt3		;a blank answer isn't acceptable
	mov	c,a		;Save length of answer
	adi	space		;Convert to encoded field-length
	sta	remdat+5	;and put in packet data area
	lda	rdl		;Get current data length
	add	c		;Count length of answer
	sta	rdl		;and store new data length
	call	cfmcmd		;Get a "confirm"
	jmp	remcom		;Do common Remote command code
;
; Common code for Remote Set commands requiring another table lookup
;
remsc1:	call	chkkey		;Get user's selection
	sta	remdat+6	;and put into the packet data area
	mvi	a,'!'		;Encoded field length for 1 char
	sta	remdat+5	;Put in packet
	lda	rdl		;Get accumulated packet data length
	adi	1		;Count length of answer (1 char)
	sta	rdl		;and store as new packet data length
	jmp	remcom		;Go do common Remote command processing
;
; Remote Status (of server) command
;
remsta:	call	cfmcmd		;Get return
	mvi	a,'Q'		;Command type (Server Status)
	sta	remdat		;...
	mvi	a,'G'		;Generic Kermit command
	sta	rcom		;...
	mvi	a,1		;1 character in packet
	sta	rdl		;...
	jmp	remcom		;Do common code
;
; Remote Type command
;
remtyp:	mvi	a,'T'		;generic type command
	jmp	remdl0		;Do common code
;
; Remote Who command
;
remwho:	lxi	h,optms		;Second argument prompt
	shld	rprmpt		;...
	mvi	a,'W'		;generic who
	jmp	remcd0		;Do common code

; Common code for Remote commands
;
remcom:
	mvi	a,0ffH		; Make sure returned info is sent
	sta	remtxt		;to the user's screen rather than to a file
	lda	rcom		;Get packet-type
	cpi	'G'		;Is it a generic command?
	jnz	remc0e		;No, go clear the screen
	lda	remdat		;Yes, get generic command type
	cpi	'S'		;Is it a Remote Set command?
	jz	remc0f		;Yes, don't clear the screen
remc0e:	call	clrtop		; clear the screen
remc0f:	xra	a
	sta	numtry		; reset retries
	sta	czseen
	sta	pktnum
	lxi	h,0
	shld	numpkt
	shld	numrtr		; clear some variables

	mvi	a,'1'		; reset block check type
	sta	curchk
remcm0:	mvi	a,'I'		; init state
	sta	state
	call	sinit		; do sendinit with I packet (??)
	lda	state		; now see if we are in the 'X' state
	cpi	'X'
	jz	remco0		;Yup, all is in order
	cpi	'A'		;No, in abort state?
	jnz	remcm0		;No, try I-packet again
	jmp	kermit		;Yes, like Danny Boy, we must die.
				;If we get this far, either the "I" packet
				;was understood or the Server couldn't
				;handle it and we ignored the error.
				;In either case, we can proceed.



remco0:	xra	a
	sta	numtry		; reset retries
	sta	czseen
	sta	pktnum
	lxi	h,0
	shld	numpkt
	shld	numrtr		; clear some variables
	mvi	a,'1'		;Make sure we use
	sta	curchk		;1-character checksum
	lda	rdl		;Get packet-length (number of bytes to copy)
	ora	a		;Anything to copy?
	  jz	remcm1		;No
	sta	temp1		;Yes, save loop counter
	lda	spsiz		;Get max packet size
	sui	5		;less overhead
	sta	temp2		;gives max chars we can send
	lxi	d,remdat		;Copy from private buffer
	lxi	h,data		;to packet data area
	lda	qbchr		;Get eightgh-bit quoting prefix char
	mov	b,a		;Save it
	lda	squote		;Get control-char quoting char
	mov	c,a		;and save it
remc0a:	lda	temp2		;Get characters to go in packet
	dcr	a		;and decrement it
	sta	temp2		;...
	jm	remc0x		;We can't copy any more
	ldax	d		;Get a packet data character
	cpi	space		;Is it a control char?
	jm	remc0b		;Yes, quote it
	cmp	c		;Is it the control-char prefix?
	jz	remc0b		;Yes, quote it
	lda	quot8		;No, is eighth-bit quoting in effect?
	ora	a		;...
	jz	remc0c		;No, just copy the character
	ldax	d		;Get character again
	cmp	b		;Is it the eighth-bit quote char?
	jnz	remc0d		;No, just copy it
remc0b:	mov	m,c		;Yes, quote the character
	inx	h		;Increment the dest. pointer
	lda	temp2		;Get chars to go
	dcr	a		;Decrement
	sta	temp2		;...
	jm	remc0x		;Can't copy any more
	lda	rdl		;Count quote prefix
	inr	a		;...
	sta	rdl		;...
remc0c:	ldax	d		;Get character again
	cpi	space		;If not a control char,
	jp	remc0d		;just copy the character, else
	adi	40H		;Convert to printing character
	ani	7fH		;modulo 128
remc0d:	mov	m,a		;Copy the character
	inx	h		;Increment the pointers
	inx	d		;...
remc0x:	lda	temp1		;Get loop counter
	dcr	a		;and decrement it
	sta	temp1		;...
	jnz	remc0a		;Copy entire packet data area
;
remcm1:	xra	a
	sta	argblk		; set packet no zero
	lda	rdl		;Number of bytes in packet
	sta	argblk+1	;into argument block
	lda	rcom		;Remote command
	call	spack		;Send the packet
	jmp	kermt3		;Nogo, die!
	jmp	remco2		;Try to get an answer

remco1:	call	nak0		;Nak packet
;

remco2:	lda	numtry		;Get number of retries
	inr	a		; update retries
	cpi	maxtry		;To many retries?
	jm	remc2a		;No
	lxi	d,erms28	;Yes, complain
	call	prtstr		;...
	jmp	kermit		;and abort

remc2a:	sta	numtry
	call	rpack		;Get a packet
	jmp	remco1		;Couldn't get one.
	cpi	'E'		;Error packet?
	jnz	remc2b		;No
	lda	rcom		;What kind of packet did we send?
	cpi	'G'		;If it wasn't generic,
	jnz	remc2f		;there is no need to start a new message line
	lda	remdat		;Packet was generic
	cpi	'S'		;Was it a Remote Set?
	cz	prcrlf		;Yes, start a new line since the screen
				;isn't blank and we would clobber the command-
				;line otherwise
remc2f:	call	error0		;Yes, inform the user
	jmp	kermit		;and abort to main command loop
remc2b:	cpi	'S'		;Send-init?
	jnz	remc2c		;No
	call	rini2a		;Initialize parameters
	lda	state		;Get state
	cpi	'A'		;If abort,
	jz	kermit		;Go back to main command loop
	mvi	a,'X'		;Set state to text-display
	sta	state		;...
	jmp	read2		;Get more packets
remc2c:	cpi	'N'		;Nacked packet?
	jz	remco2		;Yes, try again
	sta	state		;Save packet type
	call	selcon		;Select Console
	lxi	h,data		;Point to data
	lda	argblk+1	;Anything in packet data?
	ora	a		;...
	jz	remco6		;No
	push	h		;Yes, save pointer
	push	psw		;and character count
	mvi	e,'<'		;Type "<<" as in VMSKermit
	push	d		;...
	call	outcon		;...
	pop	d		;...
	call	outcon		;...
	pop	psw		;Restore character counter
	pop	h		;and data pointer
remc2d:	ora	a		;...
	jz	remc2e		;No more characters
	dcr	a		;Decrement loop counter
mov	e,m		;Get character
	inx	h		;Increment pointer
	push	psw		;Save loop counter
	push	h		;Save data pointer
	call	outcon		;Type on Console
	pop	h		;Restore pointer
	pop	psw		;Restore loop counter
	jmp	remc2d		;Type all packet data
remc2e:	mvi	e,'>'		;Type ">>" as in VMSKermit
	push	d		;...
	call	outcon		;...
	pop	d		;...
	call	outcon		;...
	call	prcrlf		;End the line
remco6:	lda	state		;Get packet type again
	cpi	'Y'		;If simple ack,
	jz	kermit		;Done, else
	call	ackp		;Acknoledge the packet
	call	countp		;Count the packet
	mvi	a,'D'		;Set to data-receive
	sta	state		;...
	jmp	read2		; do the same as read a file, but echo
				; to the screen.. Dont close non-open files.
;
;
;REMCLI - Get command-line for Remote commands
;
remcli:	xra	a		;Zero accumulated length
	sta	rcl		;...
	mov	b,a		;[12]...
;
;[MF][12]Eliminate following code which calls "comnd" in favor of code which
;[MF][12]calls "cmgtch" directly so that characters are sent without
;[MF][12]alteration or inadvertent action ("?" or <esc>). The only thing
;[MF][12]lost is the ability to produce any ASCII character via
;[MF][12]octal numbers prefixed with "\" but this isn't used much in remote
;[MF][12]commands anyway.
;
;remcl0:	mvi	a,cmtxt		;We get arbitrary text
;	call	comnd		;from the command-line
;	jmp	kermt3		;We couldn't get any.
;	ora	a		;Anything given?
;	jz	remcl1		;No, done
;	push	b		;Save BC
;	mov	c,a		;Save length
;	lda	rcl		;Get accumulated length
;	add	c		;plus current word length
;	adi	1		;plus a space
;	sta	rcl		;and save accumulated length
;	mvi	a,space		;Put in a space separator
;	stax	d		;...
;	inx	d		;Increment pointer
;	pop	b		;Restore BC
;	jmp	remcl0		;Get text to end-of-line
;remcl1:	lda	rcl		;Get accumulated length
;	ora	a		;Anything typed?
;	rz		;No
;	dcr	a		;Yes, don't count final space
;	push	psw		;Save count
;	dcx	d		;Point to final space
;	xra	a		;Zap it
;	stax	d		;...
;	pop	psw		;Restore count
;
;[MF][12]Simplified code follows
;
remcl0:	call	cmgtch		;[12]Get a character from the user
	ani	7fh		;[12]Turn off minus bit
	cpi	cr		;[12]If end-of-line,
	jz	remclx		;[12]We're done
	cpi	lf		;[12]...
	jz	remclx		;[12]...
	stax	d		;[12]else store the character
	inr	b		;[12]and count it
	inx	d		;[12]Increment character buffer pointer
	cpi	esc		;[12]is character an <esc>?
	jz	remcl2		;[12]Yes
	cpi	ff		;[12]an <ff>?
	jz	remcl1		;[12]Yes, diddle command buffer pointer
	cpi	'?'		;[12]a "?"?
	jnz	remcl0		;[12]No, just get more characters
remcl1:	push	h		;[12]Protect HL
	lhld	cmdptr		;[12]get "cmgtch"'s character pointer
	inx	h		;[12]and reverse the action at "cmgtc4"
				;[12]since we don't need a "confirm" and
				;[12]infinite loops are beaucoup bad news
	shld	cmdptr		;[12]...
	pop	h		;[12]Restore HL
remcl2:	push	psw		;[12]Save the character
	xra	a		;[12]Zero the action flag so we get input
	sta	cmaflg		;[12]to end-of-line without special action
	pop	psw		;[12]Restore the character
	jmp	remcl0		;[12]Get more characters
remclx:	mov	a,b		;[12]Get accumulated text length
	sta	rcl		;[12]and remember it
;
	ret		;Return
;
;Remote set values
;
;  REMOTE SET FILE TYPE                    300   0 = TEXT, 1 = BINARY
;  REMOTE SET FILE NAMES                   301   0 = CONVERTED, 1 = LITERAL
;  REMOTE SET FILE COLLISION               302   0 = RENAME,  1 = OVERWRITE,
;                                                2 = BACKUP,  3 = APPEND,
;                                                4 = DISCARD, 5 = ASK
;  REMOTE SET FILE REPLACE                 303   0 = PRESERVE, 1 = DEFAULT
;  REMOTE SET FILE INCOMPLETE              310   0 = DISCARD, 1 = KEEP
;  REMOTE SET INCOMPLETE (same as above)
;  REMOTE SET BLOCK-CHECK                  400   number (1, 2, or 3)
;  REMOTE SET RECEIVE PACKET-LENGTH        401   number (10-9024)
;  REMOTE SET RECEIVE TIMEOUT              402   number (any, 0 = no timeout)
;  REMOTE SET RETRY                        403   number (any, 0 = no limit)
;  REMOTE SET SERVER TIMEOUT               404   number (any, 0 = no timeout)
;REMOTE SET FILE BLOCKSIZE       311  number
;REMOTE SET FILE RECORD-LENGTH   312  number
;REMOTE SET FILE RECORD-FORMAT   313  F (fixed), V (variable), etc...
;This is just for the record, to assign these numbers to these commands
;for somebody who needed them.  Details to be filled in later.
;
;Remote Set command table
;
rmstab:	db	7		;seven entries
	db	16,'BLOCK-CHECK-TYPE$'
	dw	remsbc		;Remote Set Block Check
	db	4,'FILE$'
	dw	remsfl		;Remote Set File
	db	10,'INCOMPLETE$'
	dw	remsfi		;Remote Set (file) Incomplete
	db	7,'RECEIVE$'
	dw	remsrc		;Remote Set Receive
	db	7,'REPLACE$'
	dw	remsfr		;Remote Set (file) Replace
	db	5,'RETRY$'
	dw	remsry		;Remote Set Retry
	db	14,'SERVER-TIMEOUT$'
	dw	remsst		;Remote Set Server Timeout
;
rmshlp:	db	cr,lf,'BLOCK-CHECK-TYPE for a remote server'
	db	cr,lf,'FILE parameters for a remote server'
	db	cr,lf,'INCOMPLETE file disposition for a remote server'
	db	cr,lf,'RECEIVE parameters for a remote server'
	db	cr,lf,'REPLACE file attribute handling for a remote server'
	db	cr,lf,'RETRY maximum for a remote server'
	db	cr,lf,'SERVER-TIMEOUT interval for a remote server'
	db	'$'
;
;Remote Set File tables
;
rsftab:	db	8		;eight entries
	db	10,'BLOCK-SIZE$'
	dw	remsbs		;Remote Set File Block-size command
	db	9,'COLLISION$'
	dw	remsfc		;Remote Set File Collision command
	db	10,'INCOMPLETE$'
	dw	remsfi		;Remote Set File Incomplete command
	db	5,'NAMES$'
	dw	remsfn		;Remote Set File Names command
	db	13,'RECORD-FORMAT$'
	dw	remsrf		;Remote Set File Record-format
	db	13,'RECORD-LENGTH$'
	dw	remsrl		;Remote Set File Record-length
	db	7,'REPLACE$'
	dw	remsfr		;Remote Set File Replace command
	db	4,'TYPE$'
	dw	remsft		;Remote Set File Type command
;
rsfhlp:	db	cr,lf,'BLOCK-SIZE of files for a remote server'
	db	cr,lf,'COLLISION action on filename conflicts for a remote'
	db	' server'
	db	cr,lf,'INCOMPLETE file disposition for a remote server'
	db	cr,lf,'NAMES translation of files for a remote server'
	db	cr,lf,'RECORD-FORMAT of files for a remote server'
	db	cr,lf,'RECORD-LENGTH for a remote server'
	db	cr,lf,'REPLACE file attribute handling for a remote server'
	db	cr,lf,'TYPE of files for a remote server'
	db	'$'
;
;Remote Set File Record-format tables
;
rcftab:	db	2		;two entries
	db	5,'FIXED$'
	db	'F','F'		;Remote Set File Record-format Fixed command
	db	8,'VARIABLE$'
	db	'V','V'		;Remote Set File Record-format Variable cmd
;
rcfhlp:	db	cr,lf,'FIXED	VARIABLE'
	db	'$'
;
;Remote Set Receive tables
;
rrctab:	db	2		;two entries
	db	13,'PACKET-LENGTH$'
	dw	remrpl		;Remote Set Receive Packet-length command
	db	7,'TIMEOUT$'
	dw	remsrt		;Remote Set Receive Timeout command
;
rrchlp:	db	cr,lf,'PACKET-length	TIMEOUT'
	db	'$'
;
;Remote Set File-collision table
;
rfctab:	db	6		;six entries
	db	6,'APPEND$'
	db	'3','3'		;Set collision append
	db	3,'ASK$'
	db	'5','5'		;Set collision ask
	db	6,'BACKUP$'
	db	'2','2'		;Set collision backup
	db	7,'DISCARD$'
	db	'4','4'		;Set collision discard
	db	9,'OVERWRITE$'
	db	'1','1'		;Set collision overwrite
	db	6,'RENAME$'
	db	'0','0'		;Set collision rename
;
rfchlp:	db	cr,lf,'ASK about existing files on a remote system'
	db	cr,lf,'APPEND to existing files on a remote system'
	db	cr,lf,'BACKUP (rename) existing files on a remote system'
	db	cr,lf,'DISCARD new versions of existing files on a'
	db	' remote system'
	db	cr,lf,'OVERWRITE existing files on a remote system'
	db	cr,lf,'RENAME new versions of existing files on a'
	db	' remote system'
	db	'$'
;
;Remote Set File-Incomplete tables
;
rfitab:	db	2		;2 entries
	db	7,'DISCARD$'
	db	'0','0'		;Remote Set File Incomplete Discard
	db	4,'KEEP$'
	db	'1','1'		;Remote Set File Incomplete Keep
;
rfihlp:	db	cr,lf,'DISCARD	KEEP'
	db	'$'
;
;Remote Set File-Names tables
;
rfntab:	db	2		;two entries
	db	9,'CONVERTED$'
	db	'0','0'		;Remote Set File Names Converted
	db	7,'LITERAL$'
	db	'1','1'		;Remote Set File Names Literal
;
rfnhlp:	db	cr,lf,'CONVERTED	LITERAL'
	db	'$'
;
;Remote Set File Replace tables
;
rfrtab:	db	2		;two entries
	db	8,'PRESERVE$'
	db	'0','0'		;Remote Set File Replace Preserve
	db	7,'DEFAULT$'
	db	'1','1'		;Remote Set File Replace Default
;
rfrhlp:	db	cr,lf,'PRESERVE	DEFAULT'
	db	'$'
;
;Remote Set File Type tables
;
rfttab:	db	2		;two entries
	db	6,'BINARY$'
	db	'1','1'		;Remote Set File Type Binary
	db	4,'TEXT$'
	db	'0','0'		;Remote Set File Type Text
;
rfthlp:	db	cr,lf,'BINARY	TEXT'
	db	'$'
;
; Remote Set Block-check
;
remsbc:
IF lasm
	lxi	h,'40'		;1st 2 chars of "400"
ENDIF ;lasm
IF NOT lasm
	lxi	h,'04'
ENDIF ;NOT lasm
	shld	remdat+2	;Store in correct order
	mvi	a,'0'		;Put last char of type in buffer
	sta	remdat+4	;...
	lxi	d,blktab	;Point to block-check table
	lxi	h,blkhlp	;and help table
	jmp	remsc1		;Do common code
;
;Remote Set File command
;
remsfl:	lxi	d,rsftab	;Point to Remote Set File tables
	lxi	h,rsfhlp	;...
remsf0:	call	keycmd		;Get user's selection
	xchg		;Put dispatch address in HL
	pchl		;and obey the user's most fervent desires
;
;Remote Set Receive command
;
remsrc:	lxi	d,rrctab	;Point to the appropriate tables
	lxi	h,rrchlp	;...
	jmp	remsf0		;and do command
;
;Remote Set Block-size command
;
remsbs:
IF lasm
	lxi	h,'31'		;1st 2 chars of Set code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'13'
ENDIF ;NOT lasm
	shld	remdat+2	;Store chars in correct order
	mvi	a,'1'		;Put last char in buffer
	sta	remdat+4	;...
	jmp	remscm		;and do common Remote Set code
;
;Remote Set File-collision command
;
remsfc:
IF lasm
	lxi	h,'30'		;Put set type code in buffer
ENDIF ;lasm
IF NOT lasm
	lxi	h,'03'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'2'		;...
	sta	remdat+4		;...
	lxi	d,rfctab	;Point to tables
	lxi	h,rfchlp	;...
	jmp	remsc1		;and do common code
;
;Remote Set File Incomplete command
;
remsfi:
IF lasm
	lxi	h,'31'		;Establish command keyword code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'13'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'0'		;...
	sta	remdat+4	;...
	lxi	d,rfitab	;Point to tables
	lxi	h,rfihlp	;...
	jmp	remsc1		;and do common code
;
;Remote Set File-Names command
;
remsfn:
IF lasm
	lxi	h,'30'		;Set command code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'03'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'1'		;...
	sta	remdat+4	;...
	lxi	d,rfntab	;Point to the appropriate tables
	lxi	h,rfnhlp	;...
	jmp	remsc1		;and do common code
;
;Remote Set File Record Format command
;
remsrf:
IF lasm
	lxi	h,'31'		;Set command code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'13'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'3'		;...
	sta	remdat+4	;...
	lxi	d,rcftab	;Point to proper tables
	lxi	h,rcfhlp	;...
	jmp	remsc1		;and do common code
;
;Remote Set File Record Length command
;
remsrl:
IF lasm
	lxi	h,'31'		;Set command code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'13'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'2'		;...
	sta	remdat+4	;...
	jmp	remscm		;and do common code
;
;Remote Set File Replace command
;
remsfr:
IF lasm
	lxi	h,'30'		;Set command code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'03'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'3'		;...
	sta	remdat+4	;...
	lxi	d,rfrtab	;Point to tables
	lxi	h,rfrhlp	;...
	jmp	remsc1		;and do common code
;
;Remote Set File Type command
;
remsft:
IF lasm
	lxi	h,'30'		;Set command code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'03'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'0'		;...
	sta	remdat+4	;...
	lxi	d,rfttab	;Point to tables
	lxi	h,rfthlp	;...
	jmp	remsc1		;and go to common code
;
;Remote Set Receive Packet-length command
;
remrpl:
IF lasm
	lxi	h,'40'		;Set command code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'04'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'1'		;...
	sta	remdat+4	;...
	jmp	remscm		;and do common code
;
;Remote Set Receive Timeout command
;
remsrt:
IF lasm
	lxi	h,'40'		;Set code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'04'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'2'		;...
	sta	remdat+4	;...
	jmp	remscm		;and do common code
;
;Remote Set Retry command
;
remsry:
IF lasm
	lxi	h,'40'		;Set code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'04'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'3'		;...
	sta	remdat+4	;...
	jmp	remscm		;Go to common code
;
;Remote Set Server Timeout command
;
remsst:
IF lasm
	lxi	h,'40'		;Set code
ENDIF ;lasm
IF NOT lasm
	lxi	h,'04'
ENDIF ;NOT lasm
	shld	remdat+2	;...
	mvi	a,'4'		;...
	sta	remdat+4	;...
	jmp	remscm		;Do common code





; Little code to allow some expansion of code without changing
;  every futher address, only up to the end of this file.
;   TO BE REMOVED FOR RELEASE

;	ORG	($+100H) AND 0FF00H


IF lasm
	LINK	CPSSER		
ENDIF	;lasm