[comp.protocols.tcp-ip.ibmpc] Mods to CMU PC-IP for INT14, part 1/2

msa@clinet.FI (Markku Savela) (01/23/88)

	*FIRST*	Remember, that I cannot reply with netmail from
		this host. If you have any questions, I can receive
		them, but can reply only by posting to the news.

	These are my modifications to the CMU PC-IP package. It is
	a stripped down TELNET, which communicates through INT14-
	interface. The modules are of use only for those, who have
	the other required modules of CMU PC-IP. There is room
	for improvements. Hopefully this is usefull for some of you
	people out there -- if not, apologies for wasting net
	resources.

	I have added two new directories into my environment which
	contain the required files. The MAKEFILEs have been made
	in the "4N"-style (whatever that means).

	This message (part 1) contains the int14-catcher

	\PC-IP\SRCLIB\INT14	- int14 cather (ASM)

		MAKEFILE	- build INT144N-module and add to
				  library

		INT14TN.ASM	- source of the "catcher".

	The next message (part 2) contains the modified TELNET
	modules.

	\PC-IP\SRCCMD\BTN	- Modified Basic TN

		MAKEFILE	- Build BTN.EXE (3COM variant only)
		TELNET.H	- "tnsemulate" added
		TELNET.C	- (modified from original TELNET.C)
		BTN.C		- (modified from original TN.C)

	I use this version with the following command line

		btn <host-address> -e <terminal-emulation-command>

	I've added "-e" flag. If present, the remainder of the command
	line is executed by "system()"-call. If not present, it just
	spawns the COMMAND.COM.  (Watch out for weird effects because
	of 'exit_hook'-feature-- using "-e"-style recommended...:-).

	Notice, that the catching is "hardcoded" for DX=1 (PRN:) at
	"int14_channel" (telnet.c). Easy to change to anything you want.

	I'm not a regular UNIX-user. I post the files as a text and
	not in shar-format. Hopefully nothing gets garbled.
--
-- Markku Savela, UUCP: msa@clinet.fi
-- Nokia Information Systems (or Nokia Data Systems?)
-- P.O.BOX 780 SF-00101 HELSINKI, FINLAND
--
-*cut here*------------ \pc-ip\srclib\int14\makefile -----------------

int14tn.obj: int14tn.asm
	masm /ml int14tn;
	lib ..\..\lib\int144n-+int14tn;

-*cut here*------------ \pc-ip\srclib\int14\int14tn  -----------------

; INT14 Interrupt Catcher
;
	TITLE	int14tn

	INCLUDE	..\..\include\dos.mac

	PUBLIC	_int14_enter		; Replace INT14 vector (initialize)
	PUBLIC	_int14_exit		; Restore Original INT14 (terminate)

_TEXT	SEGMENT
	EXTRN	_int14_write:NEAR	; Send one character to telnet
	EXTRN	_int14_yield:NEAR	; Relinquish control for a while
	EXTRN	_int14_fetch:NEAR	; Get Data from net buffer
_TEXT	ENDS

_DATA	SEGMENT
	EXTRN	_int14_channel:WORD	; Channel to Intercept
	EXTRN	_int14_count:WORD	; Number of chars in buffer
	EXTRN	_int14_tcpfull:WORD	; =1, if tcpfull status!
_DATA	ENDS


INT14H		= 14H	; Interrupt Vector Number
DOS_SET_INT14	= 2514H	; Set Interrupt Vector 14h
;
;	Function codes
;
INT14_Init	= 0	; Initialize Communications port
INT14_Send	= 1	; Send one character (in AL) to line
INT14_Read	= 2	; Read one character (into AL) from line
INT14_Status	= 3	; Return Port Status

;
MODEM_Status	= 030H	; Clear to send & Data set Ready
LINE_DataReady	= 001H	; Receive Data Available
LINE_SendReady	= 060H	; Transmit Holding & Shift Register empty
LINE_Timeout	= 080H	; Timeout.


_TEXT	SEGMENT
mychannel	dw	1	; Channel to Catch
oldint14	dd	?	; Original INT14 handler (address)
intstack	dd	?	; Bottom Address of an Internal stack
extstack	dd	?	; Saved External Stack Pointer

newint14:
	cmp	dx,word ptr cs:[mychannel]	; Is this for me?
	jz	intercept			; --> YES!

	; Don't touch this -- use old interrupt service

	jmp	cs:[oldint14]
	
intercept:
	push	ds	; save registers (except AX)
	push	es
	push	si
	push	di
	push	bp
	push	bx
	push	cx
	push	dx
	sti

	mov	cx,SEG DGROUP			; Fix Datasegments !
	mov	ds,cx
	mov	es,cx

	cmp	ah,INT14_Status			; Inquire Status?
	jz	linestatus
	cmp	ah,INT14_Send			; Send Character?
	jz	sendchar
	cmp	ah,INT14_Read			; Read Character?
	jz	readchar
	cmp	ah,INT14_Init			; Initialize?
	jz	noyield
	mov	ax,0				; Unknown, return ZERO!

int14end:
	pop	dx
	pop	cx
	pop	bx
	pop	bp
	pop	di
	pop	si
	pop	es
	pop	ds
	iret

linestatus:
	cmp	_int14_count,0			; Is there anything in buffer?
	jnz	noyield				; Yes, don't release control

	mov	di,offset _int14_yield
	call	switch
noyield:
	;	Set "Send Enabled", if not tcpfull

	mov	ah,0
	cmp	_int14_tcpfull,0		
	jnz	nosend
	mov	ah,LINE_SendReady

	;	Set "Data Ready", if buffer non-empty
nosend:
	cmp	_int14_count,0
	jz	noread
	add	ah,LINE_DataReady

noread:
	mov	al,MODEM_Status
	jmp	int14end

readchar:
	cmp	_int14_count,0
	jnz	fetchdata
	mov	ax, 0100H
	jmp	int14end

fetchdata:
	mov	di,offset _int14_fetch
	call	switch
	jmp	int14end

sendchar:
	mov	di,offset _int14_write
	call	switch
	jmp	int14end

;
;	Switch from external stack to internal stack and execute one
;	c-function (address in 'di'). Pass one parameter from 'ax'.
;
switch PROC NEAR
	cli
	mov	word ptr cs:[extstack+0],sp
	mov	word ptr cs:[extstack+2],ss
	mov	sp,word ptr cs:[intstack+0]
	mov	ss,word ptr cs:[intstack+2]
	sti

	; Call C-function with internal stack

	cld
	push	bp
	mov	bp,sp
	push	ax
	call	di	

	; Restore original stack

	cli
	mov	sp,word ptr cs:[extstack+0]
	mov	ss,word ptr cs:[extstack+2]
	sti
	ret
switch ENDP

;
;	int14_enter(internal_stack_base)
;
;		This is called to initialize the INT14 catcher. Whenever
;		the normal PC-IP is called, the internal stack given here
;		is used (within PC-IP calls from INT14 are executed under
;		the process that spawned the command interpereter)
;
_int14_enter PROC NEAR
	push	bp
	mov	bp,sp

	push	si
	push	di
	push	es
	mov	ax, _int14_channel
	mov	word ptr cs:[mychannel],ax

	mov	ax,[bp+4]
	mov	word ptr cs:[intstack+0],ax	; Store Internal Stack Pointer.
	mov	word ptr cs:[intstack+2],ss	;

	push	ds
	sub	ax, ax
	mov	ds, ax
	les	bx, dword ptr ds:[INT14H * 4]
	pop	ds

	mov	word ptr cs:[oldint14], bx
	mov	word ptr cs:[oldint14+2], es

	push	ds
	push	cs
	pop	ds
	mov	dx, offset newint14
	mov	ax, DOS_SET_INT14
	int	21h
	pop	ds

	pop	es
	pop	di
	pop	si

	mov	sp,bp
	pop	bp
	ret
_int14_enter ENDP

_int14_exit PROC NEAR
	push	bp
	push	si
	push	di
	push	es
	push	ds

	mov	dx,word ptr cs:[oldint14]
	mov	ax,word ptr cs:[oldint14+2]
	mov	ds,ax
	mov	ax, DOS_SET_INT14
	int	21h

	pop	ds
	pop	es
	pop	di
	pop	si
	pop	bp
	ret
_int14_exit ENDP
	
_TEXT	ENDS
	END