	.TITLE	LNOTICE	Send System Notices to User at Login
	.IDENT	/1.01/

;++
;  Title:
;	LNOTICE	Send System Notices to User at Login
;
;  Facility:
;	Utility for displaying relevant system notices to users.
;	Invoked by SYS$LOGIN for each user's login
;
;  Abstract:
;  Program to send the system notices to the user, provided a
;  notice file has been created since the user's last login.
;  A file is maintained containing the time of last login for
;  each UIC on the system.
;
;  Environment:
;	Native mode. No other special considerations.
;
;  Author: 
;	Gary L. Grebus, Creation date: 07-Apr-1980
;	Computer Center
;	Battelle Columbus Labs
;	505 King Ave.
;	Columbus, Ohio  43201
;
;  Modified by:
;	Gary L. Grebus, 09-Apr-1980
;	1.01 - Added automatic printing of notice date and time.
;		Changed location of notice files to SYS$MAIL.
;
;--

	.PAGE

;++
;  Functional Description:
;  The user login record (ULR) file is scanned for a record containing the
;  UIC of the user.  If the UIC is not found, a new record is appended to 
;  the file.  Each version of the system notice file is opened, starting
;  with the most recent.  Each notice file created after the user's last
;  login is written to the user.  No more files are processed once a file
;  is found which is older than the user's login or when a version of
;  the message file is missing (the end of the set of message files).
;  All file manipulation is via RMS.  The ULR is a sequential, fixed-
;  record-length file.  Records are 12 bytes long and have the form:
;  ULR_L_ENTUIC)  UIC identifying the record
;  ULR_Q_ENTTIM) Time of last login for this UIC in system 64 bit format
;
;--


;  Define symbols

	$JPIDEF				;Symbols for $GETJPI call

MSG_C_MAXREC=160			;Max length (chars) of message record
ULR_C_ENTSZ=12				;Length (chars) of record in ULR file
ULR_L_ENTUIC=0				;Offset in ULR record of UIC
ULR_Q_ENTTIM=4				;Offset in ULR record of login time

;  Local macros
	.MACRO	MSG	ADDR,LEN
	$RAB_STORE -
		RAB=OUT_RAB,-
		RBF='ADDR,-
		RSZ=#'LEN		;;Point RAB at message
	$PUT	RAB=OUT_RAB		;;Issue the message
	.ENDM	MSG

	.PSECT	RWDATA	RD,WRT,NOEXE,NOSHR,LONG

;  Local data

;  RMS blocks for files
MSG_FAB:
	$FAB	FAC=GET,-
		FNM=<SYS$MAIL:SYSMSG.TXT>,-
		NAM=MSG_NAM,-
		ORG=SEQ,RFM=VAR,-
		SHR=GET,XAB=MSG_XAB	;Notice file FAB

MSG_RAB:
	$RAB	FAB=MSG_FAB,-
		UBF=MSG_LINE,-
		USZ=MSG_C_MAXREC	;Notice file RAB

MSG_XAB:
	$XABDAT				;XAB  for getting creation date

MSG_NAM:
	$NAM	RSA=MSG_FULLSPEC,-
		RSS=NAM$C_MAXRSS	;NAM to get version number

OUT_FAB:
	$FAB	FAC=PUT,-
		FNM=<SYS$OUTPUT>,-
		ORG=SEQ,RFM=VAR,RAT=CR	;FAB for writing to the user

OUT_RAB:
	$RAB	FAB=OUT_FAB		;SYS$OUTPUT RAB

ULR_FAB:
	$FAB	FAC=<GET,PUT,UPD>,-
		FNM=<SYS$MAIL:USRLOGREC.DAT>,-
		ORG=SEQ,FOP=CIF,-
		MRS=ULR_C_ENTSZ,-
		RFM=FIX			;FAB for User Login Record file

ULR_RAB:
	$RAB	FAB=ULR_FAB,-
		UBF=ULR_BUF,-
		RAC=SEQ,MBC=2,-
		USZ=ULR_C_ENTSZ		;RAB for User Login Record file

ULR_BUF:
	.BLKB	ULR_C_ENTSZ		;Buffer for ULR records

MSG_LINE:
	.BLKB	MSG_C_MAXREC		;Buffer for notice file records

MSG_FULLSPEC:
	.BLKB	NAM$C_MAXRSS		;Buffer to hold full notice file spec

JPI_LIST:
	.WORD	4
	.WORD	JPI$_UIC		;Code for UIC
	.LONG	UIC_BUF
	.LONG	0[2]			;Request block for $GETJPI

UIC_BUF:
	.BLKL	1			;Buffer to hold user's UIC

CUR_TIME:
	.BLKQ	1			;Buffer to hold current time

REC_TIME:
	.BLKQ	1			;Buffer to hold login time from
					;ULR record

WAIT_INC:
	.LONG	-2500*1000,-1		;Wait interval for busy file = .25 sec

NXT_VERS:
	.BLKL	1			;Next file version to open
	
VERS_TEXT:
	.BLKB	6			;Buffer for text of version number

VERS_TEXT_D:
	.LONG	6
	.ADDRESS	VERS_TEXT	;Desc for above buffer

VERS_L_TEXT:
	.BLKL	1			;Length of version string in buffer

VERS_CTL:
	.ASCID	/;!UL/			;Control string for coding version nr.

BLANK_LINE:
	.ASCII	/ /			;A blank

TIME_BUF:
	.BLKB	20			;Buffer to hold notice creation date
					;and time string
TIME_BUF_LEN=.-TIME_BUF

TIME_BUF_D:
	.LONG	TIME_BUF_LEN
	.ADDRESS	TIME_BUF	;Descriptor for above buffer

	.PAGE
	.PSECT	CODE	NOWRT,EXE,SHR,LONG
	.ENTRY	LNOTICE,0

;  Main program for LNOTICE
;  No registers are used except R0-R1 (scratch)

;  Get user's UIC and the current time
	$GETJPI_S	ITMLST=JPI_LIST	;Get the UIC
	BLBS	R0,30$			;Branch if success
	BRW	MSG_WRITE		;If error, force the notice
30$:	$GETTIM_S	TIMADR=CUR_TIME	;Get current time
	BLBS	R0,OPN_ULR		;Branch if success
	BRW	MSG_WRITE		;If error, force the notice

;  Create or open the User Login Record file
OPN_ULR:
	$CREATE	FAB=ULR_FAB		;Create or open if it exists
	BLBS	R0,20$			;Branch if success
	CMPL	R0,#RMS$_FLK		;Is file busy?
	BNEQ	10$			;Branch if not

	$SCHDWK_S	DAYTIM=WAIT_INC	;Wait for .25 secs
	$HIBER_S			;Sleep
	BRB	OPN_ULR			;Try again for file

;  Some other error on file. Force the notice to be issued.
10$:	BRW	MSG_WRITE

20$:	$CONNECT	RAB=ULR_RAB	;Connect the ULR record stream
	BLBS	R0,READ_ULR		;Branch if success
	BRW	MSG_WRITE		;Error - force the notice

;  Loop reading records from ULR file
READ_ULR:
	$GET	RAB=ULR_RAB		;Read next record
	BLBS	R0,20$			;Branch if success
	CMPL	R0,#RMS$_EOF		;Did we hit EOF?
	BNEQ	10$			;Branch if other error

;  We hit EOF. No record in file for this UIC. Append a new record
	MOVL	UIC_BUF,-
		ULR_BUF+ULR_L_ENTUIC	;UIC into record
	MOVQ	CUR_TIME,-
		ULR_BUF+ULR_Q_ENTTIM	;Time into record
	$RAB_STORE -
		RAB=ULR_RAB,-
		RBF=ULR_BUF,-
		RSZ=#ULR_C_ENTSZ	;Point RAB at record
	$PUT	RAB=ULR_RAB		;Write the new record

10$:	BRW	MSG_WRITE		;Force the notice to be sent

;  Does the current record match the user's UIC?
20$:	CMPL	UIC_BUF,-
		ULR_BUF+ULR_L_ENTUIC	;Compare UIC's
	BNEQ	READ_ULR		;If no match, loop

;  We have the matching record. Update it.
	MOVQ	ULR_BUF+ULR_Q_ENTTIM,-
		REC_TIME		;Save the time from the record
	MOVQ	CUR_TIME,-
		ULR_BUF+ULR_Q_ENTTIM	;Put current time into record
	$UPDATE	RAB=ULR_RAB		;Update the record
	BRW	ULR_DONE		;Done with ULR file

;  Here to force the notice file to be written
MSG_WRITE:
	CLRQ	REC_TIME		;Make login time a long time ago

ULR_DONE:
	$CLOSE	FAB=ULR_FAB		;Done with ULR file. Close it

;  Loop through all the versions of the notice file
;  Stop when a version is not found or the user has seen a version
	$OPEN	FAB=OUT_FAB		;Open SYS$OUTPUT
	$CONNECT	RAB=OUT_RAB	;And connect it

OPN_MSG:
	$OPEN	FAB=MSG_FAB		;Open the message file
	BLBS	R0,10$			;Branch if success
	BRW	FIN			;Give up if an error

10$:	$CONNECT	RAB=MSG_RAB	;Connect the file
	BLBS	R0,20$			;Branch if success
	BRW	FIN			;Give up if an error

;  Do we need to write the notice for this user?
20$:	CMPL	MSG_XAB+XAB$Q_CDT+4,-
		REC_TIME+4		;Compare upper longword of times
	BEQL	25$			;Uppers equal - need to compare lower
	BGTR	30$			;Branch if notice is newer
	BRW	FIN			;Done if notice is older
25$:	CMPL	MSG_XAB+XAB$Q_CDT,-
		REC_TIME		;Upper longwords equal - test lower
	BGEQU	30$			;Branch if notice is newer or same age
	BRW	FIN			;Done is notice is older

;  Print the message creation date and time
30$:	MSG	BLANK_LINE,1		;Skip a line
	$ASCTIM_S -
		TIMBUF=TIME_BUF_D,-
		TIMADR=<MSG_XAB+XAB$Q_CDT> ;Convert file creation date and
					;time to ASCII
	BLBC	R0,35$			;Skip this junk if failure
	MSG	TIME_BUF,TIME_BUF_LEN	;Print the time
	MSG	BLANK_LINE,1		;Skip a line

;  Loop copying notice file to SYS$OUTPUT
35$:	$GET	RAB=MSG_RAB		;Get a line
	BLBC	R0,40$			;Stop on any error
	$RAB_STORE -
		RAB=OUT_RAB,-
		RBF=MSG_LINE,-
		RSZ=<MSG_RAB+RAB$W_RSZ>	;Point RAB at record
	$PUT	RAB=OUT_RAB		;Put the line
	BRB	35$			;Loop

40$:	MSG	BLANK_LINE,1		;Skip a line
	$CLOSE	FAB=MSG_FAB		;Close this notice file

;  Compute version for next file and adjust FAB
	MOVZBL	MSG_NAM+NAM$B_RSL,R0	;Get length of full file spec
	LOCC	#^A/;/,R0,MSG_FULLSPEC	;Find beginning of the version nr.

	PUSHAL	NXT_VERS		;Arg 3 is dest of value
	ADDL3	#1,R1,-(SP)		;Arg 2 is string address+1
	SUBL3	#1,R0,-(SP)		;Arg 1 is string length-1
	CALLS	#3,LIB$CVT_DTB		;Convert version nr to binary
	DECL	NXT_VERS		;Next version to use is current-1
	BNEQ	50$			;Branch if version non_zero
	BRW	FIN			;All versions checked

;  Supply new version via default file spec field in FAB
50$:	$FAO_S	CTRSTR=VERS_CTL,-
		OUTLEN=VERS_L_TEXT,-
		OUTBUF=VERS_TEXT_D,-
		P1=NXT_VERS		;Convert version to text
	$FAB_STORE -
		FAB=MSG_FAB,-
		DNA=VERS_TEXT,-
		DNS=VERS_L_TEXT		;Supply this version via default
	BRW	OPN_MSG			;Loop for this version	

FIN:	$CLOSE	FAB=OUT_FAB		;Done with SYS$OUTPUT
	MOVL	#SS$_NORMAL,R0		;Signal normal completion
	RET				;Go home

	.END	LNOTICE
	
