.TITLE WATCHR .IDENT /V7.02/ ;******************************************************************* ; ; WATCHR.TSK ; ; THIS PROGRAM RUNS ON RSX11-M V3.2 USING SERVICES PROVIDED BY ; VERSION 7 OF THE ACCOUNTING PACKAGE. ITS FUNCTION IS TO LOG ; OFF ANY USERS THAT HAVE REMAINED IDLE AT THEIR TERMINALS FOR ; A GIVEN INTERVAL OF TIME. IT DOES THIS BY COMPARING THE ; ACCOUNTING DATA PROVIDED BY LOG... WITH THE DATA AT AN ; EARLIER TIME. IF THE VALUES ARE IDENTICAL, NOTHING HAS BEEN ; DONE AND SO THE TERMINAL IS LOGGED OFF. EXCEPTIONS: ; 1. ANY PRIVILEGED TERMINAL ; 2. ANY TERMINAL THAT HAS ACTIVE TASKS (WE DON'T WANT TO ; ABORT ANYONE WHO IS SITTING IDLE INSIDE THE EDITOR, FOR ; EXAMPLE). ; THIS PROGRAM RUNS UNTIL ABORTED. ; ; STEVE THOMPSON ; SCHOOL OF CHEMICAL ENGINEERING ; OLIN HALL ; CORNELL UNIVERSITY ; ITHACA ; NY 14853 ; ; ; REVISION HISTORY ; ---------------- ; ; SMT814 12-APR-82 LOWER CASE MESSAGES FOR RSX-11M V4.0 ; ; SMT821 23-APR-82 CHANGED ENTRY POINT NAMES OF ACCOUNTING ; SUPPORT ROUTINES (SEE MODIFY.TXT) ; ; SMT828 27-JUL-82 REPLACED "$FMTDV" BY "FM.DEV" ; ;************************************************************************* .MCALL QIOW$,DIR$,WSIG$S .MCALL ALUN$,SPWN$ .MCALL MRKT$,STSE$,WTSE$,EXST$S ACCDF$ ; DEFINE ACCOUNTING DATA STRUCTURES BITDF$ ; ;DE$BUG = 0 ; THIS SYMBOL ONLY DEFINED DURING DEBUGGING ; *** DO NOT DEFINE IT *** CR = 15 ; CARRIAGE RETURN LUN1 = 1 ; CONSOLE I/O LUN2 = 2 ; TARGET TERMINAL I/O EFN1 = 1 ; EVENT FLAG FOR CONSOLE I/O EFN2 = 2 ; EVENT FLAG FOR TARGET TERMINAL I/O EFN3 = 3 ; EVENT FLAG FOR ...BYE WAIT ; ; ********** N O T E ********** ; ; THE FOLLOWING DEFINITIONS, FOR SYMBOLS "MAXTRM", "INTRVL" ; AND "MAXCNT" ARE USER-CHANGEABLE. READ THE CODE TO ; DETERMINE THE EFFECTS ; MAXTRM = 11 ; HIGHEST PHYSICAL UNIT NUMBER OF ; TERMINAL TO EXAMINE. UNITS TT0: TO ; TT: (OR TT1: TO TT:) ; WILL BE SUBJECT TO SRUTINY. INTRVL = 10. ; INTERVAL IN MINUTES BETWEEN CHECKS MAXCNT = 2 ; INITIAL VALUE OF CHECK COUNTER ; ; MACROS ; .MACRO PRINT MES,MESSZ MOV MES,CONDPB+Q.IOPL MOV MESSZ,CONDPB+Q.IOPL+2 DIR$ #CONDPB .ENDM .MACRO WATDF$ L,B .ASECT .=0 W.CNT:'L' .BLKW 1 ; COUNTER WORD W.RUN:'L' .BLKW 1 ; NUMBER OF TASKS RUN W.LUIC:'L' .BLKW 1 ; LOGON UIC W.CPU:'L' .BLKW 2 ; CPU TIME (TICKS) .IF DF AA$QIO & AA$TCQ W.QIO:'L' .BLKW 2 ; I/O COUNT .ENDC ; DF AA$QIO & AA$TCQ W.LGTH='B'. .PSECT .MACRO WATDF$,X,Y .ENDM .ENDM WATDF$ ; DEFINE LOCAL CONTROL BLOCKS ; ; TEXT MESSAGES ; .NLIST BEX .IIF DF AA$V40, .ENABL LC .IF DF AA$TSF & P$$OFF .IFF SUPP: .ASCII /WATCHR -- No "TSF" command or P$$OFF support/ SUPPSZ=.-SUPP .IFT .IF DF DE$BUG BUF: .BLKB 100. TRMSTR: .ASCIZ /Terminal / CPUSTR: .ASCIZ / CPU=/ QIOSTR: .ASCIZ / QIO=/ .ENDC ; DF DE$BUG LOGINS: .ASCII /WATCHR -- Logging task not installed/ INSSZ=.-LOGINS LOGACT: .ASCII /WATCHR -- Logging task not active/ ACTSZ=.-LOGACT SESCAN: .ASCII /WATCHR -- Terminal session cancelled/ SESSIZ=.-SESCAN .ASCII / for / XTRA: .BLKB 20. BYE: .ASCII /BYE/ BYESZ=.-BYE .EVEN LOGNAM: .RAD50 /LOG.../ ; LOGGING TASK NAME LOGTCB: .WORD 0 ; TCB ADDRESS OF LOG... DSRPKT: .WORD 0 ; ADDRESS OF POOL PACKET UCBADR: .WORD 0 ; TERMINAL UCB ADDRESS LUIC: .WORD 0 ; LOGON UIC FOR CANCEL ROUTINE ; ; DATA STORAGE TO RECEIVE PREVIOUS VALUES OF ACCOUNTING PARAMETERS ; .EVEN TABLE: .WORD 0 ; CURRENT TABLE ENTRY ADDRESS DATTAB: .BLKB <*W.LGTH> ; DATA REGION ; ; DIRECTIVE PARAMETER BLOCKS ; .IFTF .EVEN CONDPB: QIOW$ IO.WBT,LUN1,EFN1,,,,<0,0,40> CANDPB: QIOW$ IO.WBT,LUN2,EFN2,,,, .IFT ALUN: ALUN$ LUN2,TT,0 ; ASSIGN LUN DPB TTUNIT = ALUN+A.LUNU ; DEVICE NUMBER OFFSET MARK: MRKT$ 2,INTRVL,3 ; MARK TIME DPB .IF DF S$$TOP STSEW: STSE$ EFN2 ; WAIT FOR MARK TIME DPB STSEB: STSE$ EFN3 ; WAIT FOR ...BYE DPB .IFF STSEW: WTSE$ EFN2 ; WAIT FOR MARK TIME DPB STSEB: WTSE$ EFN3 ; WAIT FOR ...BYE DPB .ENDC ; DF S$$TOP SPAWN: SPWN$ MCR...,,,377,377,EFN3,,,BYE,BYESZ,0,TT ; SPAWN ...BYE DPB VIA MCR GROUP = SPAWN+S.PWUG ; GROUP CODE OFFSET FOR SPAWN MEMBER = SPAWN+S.PWUM ; MEMBER CODE OFFSET FOR SPAWN .IFTF .PAGE .SBTTL MAIN LINE CODE $WATEP: ; XFR ADDRESS .IFF PRINT #SUPP,#SUPPSZ ; CAN'T DO IT WITHOUT TSF SUPPORT EXST$S #EX$SEV ; .IFT ; ; ZERO OUT THE DATA STORAGE REGION ; MOV #DATTAB,R0 ; GET ADDRESS OF REGION MOV #<>/2>,R1 ; GET LENGTH IN WORDS 1$: CLR (R0)+ ; ZERO A WORD DEC R1 ; DONE YET? BGT 1$ ; IF GT NO, LOOP CLR DSRPKT ; SHOW NO POOL IN USE ; ; VERIFY THAT LOGGING TASK IS INSTALLED AND ACTIVE ; 42$: MOV #LOGNAM,R3 ; GET NAME OF LOGGING TASK CALL $SRSTD ; LOOK FOR IT IN THE STD BCC 45$ ; OK PRINT #LOGINS,#INSSZ ; ERROR, IT WASN'T THERE EXST$S #EX$SEV ; EXIT WITH SEVERE ERROR 45$: BIT #TS.EXE,T.STAT(R0) ; IS THE LOGGING TASK ACTIVE? BEQ 50$ ; IF EQ YES PRINT #LOGACT,#ACTSZ ; NO, ERROR EXST$S #EX$SEV ; EXIT WITH SEVERE ERROR 50$: MOV R0,LOGTCB ; SAVE LOG...'S TCB ADDRESS ; ; ENTER WAIT LOOP BEFORE FIRST CHECK ; 5$: DIR$ #MARK ; MARK TIME FOR DESIRED INTERVAL BCS 6$ ; JUST IN CASE DIR$ #STSEW ; GO TO SLEEP UNTIL INTERVAL EXPIRES 6$: ; REF. LABEL ; ; ASSIGN LUN2 TO TARGET TERMINALS, ONE AT A TIME, AND PERFORM THE ; DESIRED CHECK ON EACH ONE. ; TASK IS SLAVED TO BYPASS LOGICAL ASSIGNMENT TABLE. ; IF THE VALUE OF THE GLOBAL SYMBOL CANTT0 (SEE WATCHRBLD.CMD) IS ; ZERO, TT0: WILL BE INCLUDED IN THE SCAN. IF IT IS NON-ZERO, ; TT0: WILL NOT BE INCLUDED. ; MOV #DATTAB,TABLE ; SET TABLE ADDRESS FOR THIS USER CLR TTUNIT ; SET TT0: FOR FIRST CHECK TST #CANTT0 ; NEED TO BYPASS TT0:? BEQ 7$ ; IF EQ NO INC TTUNIT ; TT0: SHOULD NOT BE INCLUDED ADD #W.LGTH,TABLE ; 7$: DIR$ #ALUN ; ASSIGN LUN TO THIS TERMINAL BCS 10$ ; IF CS SKIP IT CALL CHECK ; EXAMINE TERMINAL STATE 10$: ADD #W.LGTH,TABLE ; POINT TO NEXT TABLE ENTRY INC TTUNIT ; LOOK AT NEXT TERMINAL CMP TTUNIT,#MAXTRM ; AT END OF LOOP? BLE 7$ ; IF LE NO, DO NEXT ONE ; ; DEALLOCATE PACKET BACK TO POOL ; MOV DSRPKT,R0 ; GET ADDRESS OF PACKET BEQ 5$ ; IF EQ NONE, GO TO WAIT LOOP CLR DSRPKT ; SHOW THAT WE HAVE NO POOL MOV #B.LTSF,R1 ; GET LENGTH OF PACKET CALL $SWSTK,5$ ; SWITCH STACKS CALLR $DEACB ;; DEALLOCATE AND RETURN TO WAIT LOOP .PAGE .SBTTL TERMINAL EXAMINATION ROUTINE ;+ ; *** CHECK ; ; THIS ROUTINE IS CALLED EVERY SO OFTEN TO DETERMINE THE STATUS ; OF THE CURRENT TARGET TERMINAL. THE SESSION CANCELLING ACTION ; IS TAKEN ACCORDING TO THE RESULTS OF THIS ROUTINE. ; ;- CHECK: MOV TABLE,R5 ; GET CURRENT TABLE ADDRESS MOV $HEADR,R1 ; GET OUR HEADER ADDRESS MOV H.LUN+<*4>(R1),R0 ; GET UCB ADDRESS OF TARGET (LUN=2) MOV R0,UCBADR ; SAVE IT .IF DF DE$BUG MOV R0,-(SP) ; SAVE R0 MOV #BUF,R0 ; GET OUTPUT BUFFER ADDRESS MOVSTR #TRMSTR ; INSERT "TERMINAL" STRING MOV (SP),R3 ; GET UCB ADDRESS CALL FM.DEV ; FORMAT DEVICE NAME SUB #BUF,R0 ; CALCULATE MESSAGE LENGTH PRINT #BUF,R0 ; PRINT MESSAGE MOV (SP)+,R0 ; RESTORE R0 .ENDC ; DF DE$BUG BIT #U2.PRV,U.CW2(R0) ; IS TERMINAL PRIVILEGED? BNE 100$ ; IF NE YES, DO NOTHING BIT #U2.LOG,U.CW2(R0) ; TERMINAL LOGGED ON? BNE 90$ ; IF NE NO, JUST CLEAR TABLE AREA CMP W.LUIC(R5),U.LUIC(R0) ; LOGGED ON TO SAME ACCOUNT AS BEFORE? BEQ 115$ ; IF EQ YES MOV U.LUIC(R0),W.LUIC(R5) ; NO, SET UP LOGON UIC BR 100$ ; THAT'S IT ; ; NOW WE NEED TO GET THE ACCOUNTING DATA FROM LOG... ; 115$: CALL $SWSTK,140$ ; SWITCH STACKS MOV DSRPKT,R0 ;; GET ADDRESS OF DSR PACKET BNE 120$ ;; IF NE WE ALREADY HAVE ONE MOV #B.LTSF,R1 ;; GET LENGTH OF CONTROL BLOCK TO ALLOCATE CALL $ALOCB ;; GET A BLOCK BCS 130$ ;; IF CS THEN ALLOCATION FAILURE MOV R0,DSRPKT ;; SAVE ADDRESS OF CONTROL BLOCK 120$: MOV #,B.MASK(R0) ;; SET COMMAND MASK MOV $TKTCB,B.TTCB(R0) ;; INSERT OUR TCB ADDRESS MOV #,B.TTYP(R0) ;; AND REQUEST BIT MASK MOV UCBADR,B.UCB(R0) ;; SET UCB ADDRESS OF TARGET TERMINAL MOV R0,R1 ;; COPY PACKET ADDRESS TO R1 MOV LOGTCB,R0 ;; GET LOG...'S TCB ADDRESS CALL $EXRQF ;; QUEUE PACKET AND START LOG... CALLR $STPCT ;; STOP US UNTIL WE GET A REPLY 130$: RETURN ;; RETURN TO USER LEVEL 140$: MOV DSRPKT,R4 ; GET ADDRESS OF DSR PACKET BNE 150$ ; IF NE WE GOT ONE WSIG$S ; ELSE WAIT FOR SIGNIFICANT EVENT BR 115$ ; AND TRY AGAIN 150$: ; REF. LABEL ; ; COMPARE DATA WITH CURRENT TABLE ENTRY ; .IF DF DE$BUG CALL SHOW ; PRINT CURRENT PARAMETERS .ENDC ; DF DE$BUG CMP B.TTCB(R4),W.RUN(R5) ; RUN ANY MORE TASKS? BNE 80$ ; IF NE YES CMP B.CSF(R4),W.CPU(R5) ; USED ANY MORE CPU? BNE 80$ ; IF NE YES CMP B.CSF+2(R4),W.CPU+2(R5) ; MAYBE BNE 80$ ; IF NE YES .IF DF AA$QIO & AA$TCQ CMP B.ISF(R4),W.QIO(R5) ; DONE ANY MORE I/O? BNE 80$ ; IF NE YES CMP B.ISF+2(R4),W.QIO+2(R5) ; MAYBE BNE 80$ ; IF NE YES .ENDC ; DF AA$QIO & AA$TCQ ; ; NO MORE RESOURCES HAVE BEEN USED, DETERMINE IF WE HAVE TO LOGOFF ; THE TERMINAL ; INC W.CNT(R5) ; INCREMENT SESSION COUNTER CMP W.CNT(R5),#MAXCNT ; NEED TO CANCEL THE SESSION? BLT 100$ ; IF LT NO CALL CANCEL ; CANCEL THIS TERMINAL SESSION BCS 100$ ; IF CS, UNABLE TO BR 90$ ; ELSE CLEAR THE DATA AREA ; ; SESSION IS CONTINUING. SAVE NEW VALUES OF CPU AND I/O READY FOR ; NEXT CHECK ; 80$: MOV B.TTCB(R4),W.RUN(R5) ; SAVE NEW NUMBER OF TASKS MOV B.CSF(R4),W.CPU(R5) ; SAVE NEW CPU TIME MOV B.CSF+2(R4),W.CPU+2(R5) ; .IF DF AA$QIO & AA$TCQ MOV B.ISF(R4),W.QIO(R5) ; SAVE NEW I/O COUNT MOV B.ISF+2(R4),W.QIO+2(R5) ; .ENDC ; DF AA$QIO & AA$TCQ BR 100$ ; DO NEXT TERMINAL SESSION ; ; THIS LOOP CLEARS THE DATA REA FOR A TERMINAL SESSION THAT HAS ; ENDED OR HAS BEEN CANCELLED ; 90$: MOV #,R1 ; GET DATA AREA LENGTH IN WORDS 92$: CLR (R5)+ ; ZERO A WORD DEC R1 ; DONE YET? BGT 92$ ; IF GT NO, LOOP ; ; END OF ROUTINE ; 100$: RETURN ; RETURN TO CALLER .PAGE .SBTTL PARAMETERS LISTING ROUTINE ;+ ; *** SHOW ; ; THIS ROUTINE PRINTS THE CPU TIME AND I/O COUNT FOR EACH ; TERMINAL SESSION, DURING DEBUGGING ONLY. ; ;- .IF DF DE$BUG SHOW: MOV R4,-(SP) ; SAVE R4 MOV R5,-(SP) ; SAVE R5 MOV #BUF,R0 ; GET OUTPUT BUFFER ADDRESS MOVSTR #TRMSTR ; INSERT "TERMINAL" STRING MOV UCBADR,R3 ; GET UCB ADDRESS CALL FM.DEV ; FORMAT DEVICE NAME MOVSTR #CPUSTR ; INSERT "CPU=" STRING MOV R4,R1 ; POINT R1 TO CPU TIME ADD #B.CSF,R1 ; CALL FM.QIO ; FORMAT CPU TIME (AS TICKS) .IF DF AA$QIO & AA$TCQ MOVSTR #QIOSTR ; INSERT "QIO=" STRING MOV 2(SP),R1 ; POINT R1 TO I/O COUNT ADD #B.ISF,R1 ; CALL FM.QIO ; FORMAT I/O COUNT .ENDC ; DF AA$QIO & AA$TCQ SUB #BUF,R0 ; CALCULATE MESSAGE LENGTH PRINT #BUF,R0 ; AND PRINT IT MOV (SP)+,R5 ; RESTORE R5 MOV (SP)+,R4 ; RESTORE R4 RETURN ; .ENDC ; DF DE$BUG .PAGE .SBTTL TERMINAL SESSION CANCELLING ROUTINE ;+ ; *** CANCEL ; ; THIS ROUTINE IS CALLED TO TERMINATE A TERMINAL SESSION. IF ; THERE ARE ANY ACTIVE TASKS, WE DO NOTHING. ; WHEN A SESSION IS CANCELLED, THE MESSAGE ; ; TERMINAL SESSION CANCELLED ; ; APPEARS AT THE TERMINAL, FOLLOWED BY THE NORMAL DISPLAY FROM ; BYE. AFTER THE TERMINAL IS LOGGED OUT, THE DISPLAY ; ; TERMINAL SESSION CANCELLED FOR TTN:[GGG,MMM] ; ; APPEARS AT CO:. ;- CANCEL: MOV UCBADR,R3 ; GET TERMINAL UCB ADDRESS MOV U.LUIC(R3),LUIC ; SAVE CURRENT LOGON UIC ; ; DETERMINE IF ANY TASKS ARE ACTIVE AT THIS TERMINAL ; CALL $SWSTK,45$ ; SWITCH STACKS CLR 2(SP) ;; SET FLAG FOR TASK CHECK ;; 2(SP) IS THE USER STATE R0 MOV $TSKHD,R5 ;; GET SYSTEM TASK DIRECTORY LIST HEAD ;; $TSKHD RATHER THAN #$TSKHD CAUSES ;; THE FIRST ENTRY IN THE LIST (THE LOADER) ;; TO BE SKIPPED. 30$: TST T.TCBL(R5) ;; NULL TASK? BEQ 40$ ;; YES, END OF LIST CMP T.UCB(R5),UCBADR ;; TASK RUNNING AT RIGHT TERMINAL? BNE 35$ ;; NO CMP R5,$MCRPT ;; MCR? BEQ 35$ ;; YES BIT #TS.EXE,T.STAT(R5) ;; TASK ACTIVE? BNE 35$ ;; NO CMP $TKTCB,R5 ;; IS IT US? BEQ 35$ ;; YES, DON'T INCLUDE US INC 2(SP) ;; LET FLAG SHOW TASK ACTIVE AT TT: BR 40$ ;; ONE IS ENOUGH TO SHOW THAT TT: IS ACTIVE 35$: MOV T.TCBL(R5),R5 ;; POINT TO NEXT TASK BR 30$ ;; AND CHECK IT 40$: RETURN ;; 45$: TST R0 ; ANY TASKS ACTIVE? BNE 95$ ; IF BE YES, CAN'T CANCEL SESSION ; FAKE A SUCCESSFUL LOGOFF TO FORCE "CHECK" ; TO CLEAR THE DATA AREA AND RESTART FOR ; THIS TERMINAL ; ; CANCEL THE TERMINAL SESSION (NO TASKS ACTIVE) ; MOV TTUNIT,SPAWN+S.PWVT ; SET RIGHT TERMINAL FOR SPAWN MOVB LUIC+1,GROUP ; SET GROUP CODE FOR SPAWN MOVB LUIC,MEMBER ; SET MEMBER CODE FOR SPAWN DIR$ #CANDPB ; SEND SESSION CANCELLED MESSAGE DIR$ #SPAWN ; CANCEL THE SESSION BCS 110$ ; IF CS, COULDN'T CANCEL IT DIR$ #STSEB ; WAIT FOR BYE TO COMPLETE MOV #XTRA,R0 ; GET ADDRESS OF PART 2 OF BUFFER MOV UCBADR,R3 ; GET UCB ADDRESS CALL FM.DEV ; FORMAT DEVICE NAME MOV LUIC,R3 ; GET LOGON UIC CALL FM.UIC ; AND FORMAT IT AS [G,M] SUB #SESCAN,R0 ; DETERMINE STRING LENGTH PRINT #SESCAN,R0 ; SHOW IT AT CO: 95$: CLC ; ALL OK BR 110$ ; 100$: SEC ; SHOW ERROR 110$: RETURN ; .ENDC ; DF AA$TSF & P$$OFF .END $WATEP