From:	HENRY::IN%"GKN%SDSC.ARPA%SRI-KL.ARPA%relay.cs.net@rca.com" 24-DEC-1986 16:11
To:	DHaskin%ClarkU.BITNET@WISCVM.WISC.EDU,
Subj:	LAT info

Todd, Denis, Arno and Info-VAX readers in general:

There have been several questions regarding LAT on the list lately, so
here is a subroutine and an example program which will retrieve the name
of the server, the port name and session number of a given LAT terminal
connection.

Please note that this routine will work ONLY with LAT Plus V01.012 and with
VMS V4.2 or higher.  It requires CMKRNL.  The routine itself is as paranoid
about argument checking as I know how to make it, so the chances of it
crashing your system are pretty low.  However, as pointed out in the recent
past, one should never test privileged code on a system where there are real
live users who might get angry if the system ceases to work...

It works fine on my V4.5 cluster, and the code was derived from a program
I've been running since V4.2.

Please check the version of your LTDRIVER.EXE with ANALYZE/IMAGE and ensure
that it says "LATPLUS V01.012" before running a program which calls this
routine.

Digital considers the LAT protocol proprietary, and therefore does not
publish anything about it, and has removed the listings of LTDRIVER and
LATCP from the uFiche as of VMS V4.4.  I figured out enough about the
format of a LT UCB using SDA one afternoon to be able to retrieve this
information.  However, since LAT is subject to change, this routine may
cease to work in the future.  I know it will NOT work with older versions
of LAT.

To build the example program, do:

	$ Macro LAT_INFO
	$ Fortran LAT
	$ Link LAT+LAT_INFO


Hope this helps.

gkn
--------------------------------------
Arpa:	GKN@SDSC.ARPA
Bitnet:	GKN@SDSC
Span:	SDSC::GKN (5.600)
USPS:	Gerard K. Newman
	San Diego Supercomputer Center
	P.O. Box 85608
	San Diego, CA 92138
AT&T:	619.534.5076

-------------------------------------LAT.FOR------------------------------------
	Program	LAT

	Include '($JPIDEF)'

	Character Server*24, Port*16, Terminal*16
	Integer	  Session, Status, LIB$GETJPI, LAT_INFO, SYS$EXIT

	External  LIB$GETJPI, LAT_INFO, SYS$EXIT

	Call LIB$GETJPI (JPI$_TERMINAL,,,,Terminal,)
	Status = LAT_INFO (Terminal, Session, Server, Port)
	If (.not. Status) Call SYS$EXIT(%Val(Status))
	Write (6,100) Terminal, Server, Port, Session
	Call SYS$EXIT(%Val(1))

100	Format (1X,'Terminal: ',A,'  Server: ',A,'  Port: ',A,
	1	'  Session: ',I2)

	End
---------------------------------LAT_INFO.MAR-----------------------------------
	.Title	LAT_Info	- Get information about a LAT terminal
	.Ident	/V01.000/
	.Enable	SUP
	.Default Displacement,Word
	.Subtitle	Introduction

;+
;
; ----- LAT_Info:  Get information about a LAT terminal
;
;
; Facility:
;
;	VAX/VMS system programming
;
; Abstract:
;
;	This module provides a routine which can be called from any
;	VAX native  language to obtain information about a specific
;	LAT terminal.
;
; Environment:
;
;	VAX/VMS native mode, VMS V4.2 or later, LATPlus V01.012, CMKRNL
;	privilege.
;
;
;
; Version:	V01.000
; Date:		19-Dec-1986
;
; Gerard K. Newman	
; San Diego Supercomputer Center
; GA Technologies
; P.O. Box 85608
; San Diego, CA  92138
; 619.534.5076
;
; GKN@SDSC.ARPA, GKN@SDSC.BITNET
;
; Modifications:
;
;
;-

	.Page
	.Subtitle	Local definitions

	.Library "SYS$LIBRARY:LIB"			;Get special macros from here
	.Link	 "SYS$SYSTEM:SYS.STB"/Selective_Search	;Ease the link process a bit

	.NoCross			;Save a tree

	$DCDEF				;Device class & type definitions
	$DDBDEF				;Device data block offsets
	$SSDEF				;System service codes
	$TTYUCBDEF			;Terminal UCB offsets
	$UCBDEF				;UCB offsets

	.Cross				;Turn CREF back on


; Local definitions

; Constants that are likely to change in a future release of VMS that are not
; defined in SYS.STB  or in a macro anywhere.  These values come from looking
; at the running system with SDA.

; Offset in an LT UCB to the length of the port name, which is a counted
; string.  Immediately following the port name is another counted string
; which is the LAT node name.

UCB$B_LT_PORT	=	^X134		;Offset to the port name length
UCB$B_LT_SESS	=	^X195		;Offset to the session number

	.Page
	.Subtitle	LAT_INFO	- Get information about a LAT terminal

;+
;
; ----- LAT_INFO:  Get information about a LAT terminal
;
;
; This routine can be called by any VAX native language to obtain the server
; name, port name  and session number of a  LAT connection given a LT device
; name.  The calling program must have  CMKRNL privilege and  must be linked
; with SYS.STB.
;
; Caveats:
;
;	Will only work with fixed (non-dynamic) string descriptors.
;
; Call sequence:
;
;	status.wlv = LAT_INFO (terminal.rt.dx, session.wlr, server.wt.dx, port.wt.dx)
;
; Inputs:
;
;	4(AP)	- Address of a descriptor of the LT device name.
;	8(AP)	- Address of a longword to return the session number in.
;	12(AP)	- Address of a descriptor to return the server name.
;	16(AP)	- Address of a descriptor to return the server port name.
;
; Outputs:
;
;	R0	- SS$_NOPRIV:	 No CMKRNL privilege.
;		- SS$_ACCVIO:	 One of the arguments is not accessible.
;		- SS$_NOSUCHDEV: The specified LT device can't be found.
;		- SS$_IVDEVNAM:	 The specified device isn't a LAT terminal.
;		- SS$_NORMAL:	 Success.
;
;-

	.Psect	LAT_INFO	EXE,RD,NOWRT,PIC,SHR,PAGE

	.Entry	LAT_INFO,^M<>		;Entry here

	$CMKRNL_S ROUTIN=B^20$,-	;Do this
		ARGLST=(AP)		; in kernel mode

10$:	RET				;Done, status in R0

; Here in kernel mode to do all of the actual work.

20$:	.Word	^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11> ;Here in kernel mode to get some info

; First, check to see if we can read the argument list.

	MOVL	#SS$_ACCVIO,R0		;Presume we can't
	IFNORD	#<5*4>,(AP),10$		;Probe the argument list

; Check the number of arguments

	MOVL	#SS$_INSFARG,R0		;Presume we have too few arguments
	CMPB	#4,(AP)			;Do we have enough arguments?
	BNEQ	10$			;If NEQ no, it's wrong somehow

; Check to see if we can write the session number.

	MOVL	#SS$_ACCVIO,R0		;Presume we can't
	IFNOWRT	#4,@8(AP),10$		;Probe the output session number

; See if we can read the device name descriptor.

	MOVL	4(AP),R1		;Address the LT device name descriptor
	JSB	G^EXE$PROBER_DSC	;Probe the descriptor
	BLBC	R0,10$			;Sigh.
	MOVQ	R1,-(SP)		;Save a safe copy of the probed descriptor
	MOVL	SP,R11			;Remember where it is
	CLRW	2(R11)			;Never mind the type and class info

; See if we have write access to the two output descriptors.

	MOVL	12(AP),R1		;Address the server name output descriptor
	JSB	G^EXE$PROBEW_DSC	;Probe the descriptor
	BLBC	R0,10$			;Sigh.
	MOVQ	R1,-(SP)		;Stash a safe copy of the descriptor
	MOVL	SP,R10			;Remember where I put it
	CLRW	2(R10)			;Never mind the type and class info
	MOVL	16(AP),R1		;Address the port name output descriptor
	JSB	G^EXE$PROBEW_DSC	;Probe the descriptor
	BLBC	R0,10$			;Sigh.
	MOVQ	R1,-(SP)		;Stash a safe copy of said descriptor
	MOVL	SP,R9			;Remember where it is
	CLRW	2(R9)			;Never mind the type and class info

; Ok.  Now go hunt down the device the user told us was a LAT terminal
; and see if it really is.

	MOVL	G^SCH$GL_CURPCB,R4	;Get my PCB address
	JSB	G^SCH$IOLOCKR		;Lock the I/O database mutex
	MOVL	R11,R1			;Address the device name descriptor
	JSB	G^IOC$SEARCHDEV		;Go search for the device.
	BLBC	R0,30$			;We lose.

; Now check to see if it's even a terminal, and if it is see if it's a LAT
; terminal.  Remember to chain  to the physical UCB  first in case this is
; a disconnectable terminal.

	MOVL	#SS$_IVDEVNAM,R0	     ;Presume it isn't a terminal
	MOVL	UCB$L_TL_PHYUCB(R1),R1	     ;Get to the "real" UCB
	CMPB	#DC$_TERM,UCB$B_DEVCLASS(R1) ;Is it a terminal?
	BNEQ	30$			     ;If NEQ no.
	MOVL	UCB$L_DDB(R1),R2	     ;Find the DDB
	CMPW	#^A/LT/,DDB$T_NAME+1(R2)     ;Is this a LAT terminal?
	BNEQ	30$			     ;If NEQ no

; It's a LAT terminal all right.  Obtain the server name, port name and
; session number.

	MOVZBL	UCB$B_LT_SESS(R1),@8(AP) ;Stash the session number
	MOVAB	UCB$B_LT_PORT(R1),R1	 ;Address the port name
	MOVL	R9,R6			 ;Here's the output descriptor address
	BSBB	MOVE_ASCIC		 ;Move the port name
	MOVW	(R6),@16(AP)		 ;Replace the length
	MOVL	R10,R6			 ;R1 now points at the server name
	BSBB	MOVE_ASCIC		 ;So go move it, too
	MOVW	(R6),@12(AP)		 ;Replace the length
	MOVL	#SS$_NORMAL,R0		 ;Success!

30$:	PUSHL	R0			;Save the return status
	MOVL	G^SCH$GL_CURPCB,R4	;Get my PCB address again
	JSB	G^SCH$IOUNLOCK		;Unlock the I/O database mutex
	SETIPL	#0			;Drop back down from IPL$_ASTDEL
	POPL	R0			;Restore the return status
	RET				;Back to user mode

; Short subroutine to move a .Ascic string to a place described by a
; descriptor.  Forms a  proper descriptor of the result, and handles
; short buffers, etc.
;
; Inputs:
;
;	R1	- Address of the .Ascic string
;	R6	- Address of the output descriptor
;
; Outputs:
;
;	R1	- Address of one byte past the end of the .Ascic string
;	R0-R5	- Smashed

MOVE_ASCIC:				;Here to move a .Ascic string

	MOVZBL	(R1)+,R0		;Grab the string length
	CMPW	(R6),R0			;Check the string length
	BGEQU	10$			;If GEQU then we can use it
	MOVZWL	(R6),R0			;Else only copy what will fit

10$:	MOVW	R0,(R6)			;Stash the length
	MOVC3	R0,(R1),@4(R6)		;Copy the string
	RSB				;Done


	.End
--------------------------------------------------------------------------------
[end of message]
-------
