.TITLE ISUMONITR .IDENT \ISUQUOTA 2.9\ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ISUMONITR RUNS AS A DETACHED PROCESS. ITS FUNCTION IS TO ENFORCE ; CONNECT TIME QUOTAS AND DETECT PROCESSES WHICH BYPASS ISULOGOUT. ; ; ISUMONITR STORES PROCESS AND QUOTA INFORMATION IN TWO TYPES OF ; QUEUES, USER AND PRCS. THE ENTRIES IN THESE QUEUES ARE UNIQUE, ; USER QUEUE ENTRIES KEYED BY USERNAME AND PRCS QUEUE ENTRIES KEYED ; BY PID. THE USER QUEUE ENTRY CONTAINS CUMULATIVE SESSION USAGE ; DATA AND THE QUEUE_HEAD FOR THE QUEUE CONTAINING "ALL" PROCESSES ; WITH THIS UIC. THE PRCS QUEUE CONTAINS PROCESS SPECIFIC DATA AND ; A BACK POINTER TO ITS USER PARENT. ; ; DATA IS TRANSFERRED TO ISUMONITR THROUGH A PERMANENT MAILBOX. ; IF THE RECORD TYPE IS LOGIN, SENT BY ISULOGIN, A USER QUEUE ENTRY ; IS CREATED FOR THE PROCESS USERNAME (IF ONE DOES NOT EXIST) AND A ; PROCESS ENTRY IS QUEUED TO THE USER QUEUE ENTRY. IF THE RECORD ; TYPE IS LOGOUT, SENT BY ISULOGOUT, THE PROCESS ENTRY IS MARKED AS ; HAVING GONE THROUGH LOGOUT ACCOUNTING. IF THE RECORD TYPE IS ; ACCOUNTING, SENT BY $DELPROC TO A TERMINATION MAIBOX, THE PROCESS ; ENTRY IS EITHER REMOVED FROM THE QUEUE (IF IT WENT THROUGH ISULOGOUT) ; OR ISU ACCOUNTING IS PERFORMED, AND THE PROCESS ENTRY IS MARKED AS ; HAVING BYPASSED LOGOUT PROCESSING. ; ; A TIMER TASK IS ENABLED PERIODICALLY TO EXAMINE THE PROCESSES WITH ; CONNECT TIME QUOTAS ENFORCED AND DECREMENT THEIR CONNECT TIME QUOTA. ; IF THE CONNECT TIME EXPIRES A WARNING IS $BRDCST TO THE TERMINAL (FOR ; INTERACTIVE PROCESSES). THE PROCESS ENTRY IS GIVEN AN EXTENSION, AND ; THE PROCESS MARKED AS WARNED. IF THE CONNECT TIME EXPIRES FOR A ; WARNED PROCESS A MESSAGE IS $BRDCST TO THE TERMINAL (INTERACTIVE ONLY). ; THE PROCESS IS DELETED, AND THE PROCESS ENTRY IS MARKED AS KILLED ; (KILLED PROCESSES ARE REMOVED WHEN THEIR TERMINATION MAILBOX ACCOUNTING ; RECORD COMES THROUGH). IF THE CONNECT TIME EXPIRES FOR A BYPASSED ; LOGOUT PROCESS, A DETACHED PROCESS IS CREATED TO RUN ISULOGOUT. THIS IS ; A DEFERRED LOGOUT PROCESS. (BYPASSED LOGOUT PROCESSES ARE REMOVED IF AN ; INTERACTIVE PROCESS LOGS IN BEFORE THE CONNECT TIME EXPIRES FOR THE ; BYPASS LOGOUT PROCESS). THE BYPASSED LOGOUT PROCESS ENTRY IS ALTERED ; TO CONTAIN THE DEFERRED LOGOUT PROCESS INFORMATION. WHEN THE DEFERRED ; PROCESS COMPLETES, ACCOUNTING IS PERFORMED AND THE PROCESS ENTRY IS ; REMOVED FROM THE QUEUE. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; ANTHONY E. BIBLE ; 104 COMPUTER SCIENCE ; ISU COMPUTATION CENTER ; IOWA STATE UNIVERSITY ; AMES, IA 50011 ; ; 515-294-5659 ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .PAGE .SBTTL SYMBOLS & MACROS ; SYMBOLS ; SYSTEM MACROS $ACCDEF $DVIDEF $IODEF $MSGDEF $OPCDEF $PRVDEF $RMSDEF $SSDEF ; USER MACROS ACCOFFDEF AFACTR ACCOFFDEF COST BFBDEF ISUACCDEF MTSKDEF PRCSDEF TSKDEF TTCONNDEF USERDEF QUAXDEF QUOMSGDEF REPLYDEF .PAGE .SBTTL LOCAL READ-ONLY DATA .PSECT LCLRODATA,RD,NOWRT,NOEXE,LONG ADR_PURGWS: .LONG 0 .LONG ^X7FFFFFFF PRV_DFRLO: .LONG 1@PRV$V_TMPMBX .LONG 0 DELTA_T: .LONG -30*10*1000*1000,-1 ; PROC_TIMER INTERVAL MAX_ACCRETRY: .LONG 2 EXT_CONN: .LONG 60*5 ; 5 MINUTES CONNECT TIME EXTENSION EXT_BYPASLO: .LONG 60*10 ; 10 MINUTES TO DEFERRED LOGOUT STRG_TT: .ASCII \TT\ OP_TTCONN_GET: .LONG TT_K_GET OP_TTCONN_UPD: .LONG TT_K_UPD LST_TASK: .WORD TSK_K_LOGIN .WORD TSK_K_LOGOUT .WORD TSK_K_ALTER .WORD TSK_K_DELPROC .WORD TSK_K_TIMER N_LST_TASK= .-LST_TASK/2 LST_TASK_PROC: .LONG PROC_LOGIN .LONG PROC_LOGOUT .LONG PROC_ALTER .LONG PROC_DELPROC .LONG PROC_TIMER LST_DLOMBXUNT: .WORD 4 .WORD DVI$_UNIT .LONG UNIT_DLOMBX .LONG 0 .LONG 0 ; END GETDVI LIST DSC_ISUMONMBX: .ASCID \ISUMONMBX\ DSC_ISUDLOMBX: .ASCID \ISUDLOMBX\ DSC_ISUQUOTA: .ASCID \ISUQUOTA\ DSC_ISULOGOUT: .ASCID \TSTQUO:ISULOGOUT\ DSC_NLA0: .ASCID \NLA0:\ DSC_FREEUSER: .ASCID \FREE_USER\ DSC_FREEBFB: .ASCID \FREE_BUFBLK\ DSC_FREEMTSK: .ASCID \FREE_MISCTSK\ .PAGE .SBTTL LOCAL READ-WRITE DATA .PSECT LCLRWDATA,RD,WRT,NOEXE,LONG ADR_USER: .BLKL 1 ADR_PRCS: .BLKL 1 ARG_REMPRCS: .BLKL 1 ARG_REPLY: .BLKL 1 ARG_ACCTG: .BLKL 1 ARG_EMPTYQUE: .BLKL 1 ARG_UNLOCK: .BLKL 1 PID: .BLKL 1 ADR_USERNAME: .BLKL 1 CHAN_REPLY: .BLKW 1 BUFR_REPLY: .BLKB REPLY_K_LENGTH STS_REPLY: .BLKQ 1 STRG_MSGTXT: .BLKB REPLY_K_LENTXT STS_ISUMONITR: .BLKQ 1 CHAN_MONMBX: .BLKW 1 CHAN_DLOMBX: .BLKW 1 UNIT_DLOMBX: .BLKW 1 DYN_UMBXNAM: .BLKQ 1 DYN_OPRMSG: .LONG 0 .LONG 10$ 10$: .LONG OPC$_RQ_RQST!^X100*OPC$M_NM_CENTRL .LONG 0 .BLKB 120 DSC_WRTLOG_ACC: .LONG END_WRTLOG_ACC-BUFR_WRTLOG_ACC .LONG BUFR_WRTLOG_ACC BUFR_WRTLOG_ACC: ;;;;;;;;; .WORD ACC$K_INSMESG ; .BYTE END_WRTLOG_ACC-. ; .WORD ISUACC_K_ACCTG ; .WORD ISUACC_K_ISUMON ; USERNAME: ; .BLKB 12 ; LOGIN_TIME: ; .BLKQ 1 ; UIC: .BLKL 1 ; ACCOUNT: ; .BLKB 8 ; TAB_COST: ; .BLKL N_COST ; TAB_ACCFACTR: ; .BLKL N_AFACTR ; ACC_QUENAM: ; .BLKB 16 ; END_WRTLOG_ACC: ;;;;;;;;; DYN_MSG_SNDTT: .LONG 0 .LONG MSG_SNDTT DSC_MSG_SNDTT: .LONG MSG_SNDTT_L .LONG MSG_SNDTT MSG_SNDTT: .BLKB 120 MSG_SNDTT_L= .-MSG_SNDTT ALST_SNDTT_FAOL: .BLKL 10 N_SND_FAOL= .-ALST_SNDTT_FAOL/4 MSGID_SNDTT: .BLKL 1 DELTA_CONN: .BLKL 1 FLG_DO_ACCTG: .BLKB 1 FLG_ASTMONITR: .BLKB 1 DMY_BUFBLK: .BLKB BFB_K_LENGTH GBL_COUNT_IAC: .LONG 0 WORK: .BLKB 4*10 .PAGE .SBTTL QUEUE DATA .PSECT QUEDATA,RD,WRT,NOEXE,LONG QHD_TASK: .LONG QHD_TASK .LONG QHD_TASK QHD_MISCTSK: .LONG QHD_MISCTSK .LONG QHD_MISCTSK QHD_USER: .LONG QHD_USER .LONG QHD_USER FREE_USER: .LONG FREE_USER .LONG FREE_USER N_USER= 128 FREE_BUFBLK: .LONG FREE_BUFBLK .LONG FREE_BUFBLK N_BUFBLK= 256 FREE_MISCTSK: .LONG FREE_MISCTSK .LONG FREE_MISCTSK N_MISCTSK= 64 .PAGE .SBTTL RMS CONTROL BLKS .PSECT RMSBLKS,RD,WRT,NOEXE,LONG FAB_ERROR: $FAB FNM= RAB_ERROR: $RAB FAB=FAB_ERROR FAB_QUAX: $FAB FNM=,- FAC=,- RFM=FIX,- MRS=QXR_K_LENGTH,- BKS=1,- SHR=,- ORG=IDX,- XAB=KEY0_QUAX RAB_QUAX: $RAB FAB=FAB_QUAX,- RBF=QUAX,- RSZ=QXR_K_LENGTH,- UBF=QUAX,- USZ=QXR_K_LENGTH,- RAC=KEY,- ROP=TMO KEY0_QUAX: $XABKEY REF=0,- POS=QXR_USERNAME,- SIZ=QXR_K_LENUSRNAM,- NXT=KEY1_QUAX KEY1_QUAX: $XABKEY REF=1,- POS=QXR_UIC,- SIZ=4 QUAX: .BLKB QXR_K_LENGTH .PAGE .SBTTL MSGVEC'S FOR ISUMONITR .PSECT MSGVECS,RD,WRT,NOEXE MSG_STARTUP: .LONG 3 .LONG ISUQUO_STARTUP .LONG 1 .LONG 0 MSG_ERREXIT: .LONG 5 .LONG ISUQUO_ERREXIT .LONG 3 .LONG 0 .BLKL 2 MSG_DFRLOFAIL: .LONG 5 .LONG ISUQUO_DFRLOFAIL .LONG 3 .LONG 0 .BLKL 2 MSG_ACCFAIL: .LONG 5 .LONG ISUQUO_ACCFAIL .LONG 3 .LONG 0 .BLKL 2 MSG_EMPTYQUE: .LONG 5 .LONG ISUQUO_EMPTYQUE .LONG 3 .LONG 0 .BLKL 2 MSG_BADMTSK: .LONG 4 .LONG ISUQUO_BADMTSK .LONG 2 .LONG 0 .LONG 1 MSG_BADTTNAM: .LONG 5 .LONG ISUQUO_BADTTNAM .LONG 3 .LONG 0 .BLKL 2 MSG_NODFRLO: .LONG 4 .LONG ISUQUO_NODFRLO .LONG 2 .LONG 0 .BLKL 1 MSG_EXISTPRCS: .LONG 3 .LONG ISUQUO_EXISTPRCS .LONG 1 .LONG 0 MSG_NOSUCHPRC: .LONG 3 .LONG ISUQUO_NOSUCHPRC .LONG 1 .LONG 0 .PAGE .SBTTL CODE .PSECT CODE,RD,NOWRT,EXE,LONG .ENTRY ISUMONITR,^M ; INITIALIZE VALUES, CREATE MAILBOX AND QUEUES, AND ENABLE AST'S. ; LOOP THROUGH ALL PENDING TASKS. THERE ARE FOUR POSSIBLE TASKS: ; 1. LOGIN SENT BY ISULOGIN ; 2. LOGOUT SENT BY ISULOGOUT ; 3. ACCOUNTING SENT BY THE SYSTEM $DELPROC ; 4. TIMER PROCESSING ; ; WHEN ALL TASKS HAVE BEEN COMPLETED THE PROCESS HIBERNATES UNTIL A ; TASK IS GENERATED BY A WRITE TO THE MAILBOX OR TIMER EXPIRED. JSB PROC_INIT ; INITIALIZATION $PURGWS_S INADR=ADR_PURGWS ; RLSE MEMORY LOOP_TASK: REMQUE @QHD_TASK,R11 ; R11= CURRENT TASK BVS Z_Z_Z_Z ; TASK QUEUE IS EMPTY CLRL R6 ; LOOP INDEX 10$: CMPW BFB_TYPE(R11),LST_TASK[R6] ; FIND TASK TYPE BEQL 20$ AOBLSS #N_LST_TASK,R6,10$ BRB CONT_TASK ; IGNORE INVALID TASKS TYPE 20$: MOVL LST_TASK_PROC[R6],R6 ; DO TASK JSB (R6) CONT_TASK: BRW LOOP_TASK ; CONTINUE TASK LOOP Z_Z_Z_Z: $HIBER_S ; BAGGING Z'S BRW LOOP_TASK ; UP AND AT'EM ATOM ANT! .PAGE .SBTTL PROC_LOGIN ; THIS ROUTINE ENTERS NEW PROCESSES ONTO THE USER PRCS QUEUE USING DATA ; SENT THROUGH ISUMONMBX BY ISULOGIN. IF A USER QUEUE ENTRY DOES NOT ; EXIST FOR THE PRCOCESS'S USERNAME THEN ONE IS CREATED. IF THE NEW ; PROCESS IS INTERACTIVE THEN ALL INTERACTIVE/BYPASS PRCS QUEUE ENTRIES ; FOR THIS USER ARE REMOVED. IF THE USERNAME IS LOCKED THEN THE REPLY ; IS DEFERRED UNTIL THE USERNAME IS UNLOCKED. MASK_LOGIN= ^M PROC_LOGIN: PUSHR #MASK_LOGIN ; SAVE WORK REGISTER MOVAB BFB_BUFR(R11),R10 ; ADR MBX BUFFER MOVQ #SS$_NORMAL,STS_REPLY ; INIT REPLY STATUS MOVL BFB_IOSB+4(R11),PID ; FIND PRCS MOVAB PRCS_USERNAME(R10),ADR_USERNAME JSB PROC_FIND MOVL ADR_USER,R9 ; ADR USER ENTRY TSTL ADR_PRCS ; PRCS ALREADY EXISTS? BEQL 10$ ; NO CLRQ STS_REPLY ; ERROR STATUS $PUTMSG_S MSGVEC=MSG_EXISTPRCS,- ; GENERATE REPLY MSG ACTRTN=MSGACTRTN,- ACTPRM=#0 MOVC3 #REPLY_K_LENTXT,STRG_MSGTXT,- ; INSERT MESSAGE FOR REPLY BUFR_REPLY+REPLY_MSGTXT BRW LOGIN_REPLY 10$: TSTL R9 ; USER ALREADY EXISTS? BNEQ LOGIN_PRCS ; YES REMQUE @FREE_USER,R9 ; GET USER ENTRY FOR NEW USERNAME BVC LOGIN_USER MOVAQ DSC_FREEBFB,ARG_EMPTYQUE ; LOG USER QUEUE EMPTY JSB PROC_LOGMPTYQUE CLRQ STS_REPLY ; SET FAILED STS FOR REPLY MOVC3 #REPLY_K_LENTXT,STRG_MSGTXT,- ; INSERT FAILURE MSG FOR REPLY BUFR_REPLY+REPLY_MSGTXT BRW LOGIN_REPLY LOGIN_USER: MOVL R9,ADR_USER ; SAVE USER ENTRY ADR MOVAQ USER_QHD_PRCS(R9),USER_QHD_PRCS(R9) ; INIT USER ENTRY MOVL USER_QHD_PRCS(R9),USER_QHD_PRCS+4(R9) CLRL USER_FLAGS(R9) CLRL USER_COUNT(R9) CLRL USER_CNT_IAC(R9) MOVC3 #QXR_K_LENUSRNAM,PRCS_USERNAME(R10),USER_USERNAME(R9) MOVL PRCS_UIC(R10),USER_UIC(R9) INSQUE (R9),@QHD_USER+4 ; INSERT AT END OF USER QUEUE LOGIN_PRCS: MOVL R11,ADR_PRCS ; SAVE PRCS ENTRY ADR MOVL R9,BFB_ADRUSER(R11) ; PTR TO USER PARENT INSQUE (R11),@USER_QHD_PRCS+4(R9) ; ENTER PRCS ENTRY ON QUEUE INCL USER_COUNT(R9) ; COUNT CURRENT ACTIVE PRCS BITL #PRCS_M_IAC,PRCS_TYPE(R10) ; INTERACTIVE PRCS? BEQL 10$ ; NO INCL USER_CNT_IAC(R9) ; COUNT CURRENT IAC PRCS INCL GBL_COUNT_IAC ; COUNT TOTAL ISUQUOTA IAC PRCS PUSHL R11 ; GET CURRENT CONN QUOTA CALLS #1,TTCONNGET 10$: BITL #QMSK_M_BYPASLO,PRCS_QMASK(R10) ; BYPASS LOGOUT ENFORCED? BEQL LOGIN_REPLY ; NO JSB PROC_ABORTDFRLO ; REMOVE ANY PENDING DFRLO PRCS LOGIN_REPLY: BITL #USER_M_LOCK,USER_FLAGS(R9) ; LOCKED USERNAME? BEQL 10$ ; NO BISL #PRCS_M_RPLYPND,PRCS_STATE(R10) ; MARK REPLY PENDING BRB RSB_LOGIN 10$: MOVL R11,ARG_REPLY ; ADR BUFBLK FOR REPLY JSB PROC_REPLY ; SEND STATUS BACK TO ISULOGIN RSB_LOGIN: POPR #MASK_LOGIN ; RESTORE WORK REGISTER RSB .PAGE .SBTTL PROC_LOGOUT ; THIS ROUTINE MARKS A PROCESS LOGGED OUT USING DATA SENT THROUGH ; ISUMONMBX BY ISULOGOUT. MASK_LOGOUT= ^M PROC_LOGOUT: PUSHR #MASK_LOGOUT ; SAVE WORK REGS MOVAB BFB_BUFR(R11),R10 ; ADR LOGOUT DATA MOVQ #SS$_NORMAL,STS_REPLY ; INIT SUCCESS STATUS MOVAB PRCS_USERNAME(R10),ADR_USERNAME ; FIND PRCS BUFBLK MOVL BFB_IOSB+4(R11),PID JSB PROC_FIND MOVL ADR_PRCS,R8 ; ADR PRCS BUFBLK BNEQ 10$ CLRL STS_REPLY ; UNKNOWN PROCESS REPLY STATUS $PUTMSG_S MSGVEC=MSG_NOSUCHPRC,- ; GENERATE MSG ACTRTN=MSGACTRTN,- ACTPRM=#0 MOVC3 #REPLY_K_LENTXT,STRG_MSGTXT,- ; INSERT MSG TEXT FOR REPLY BUFR_REPLY+REPLY_MSGTXT BRB RSB_LOGOUT 10$: MOVAB BFB_BUFR(R8),R7 ; ADR PRCS DATA BITL #PRCS_M_DLO,PRCS_TYPE(R7) ; DEFERRED LOGOUT PRCS? BEQL 15$ ; NO JSB PROC_UNLOCK ; UNLOCK USERNAME 15$: MOVL #PRCS_M_LOGOUT,PRCS_STATE(R7) ; MARK PRCS LOGOUT COMPLETED MOVQ PRCS_LOGOUT_T(R10),PRCS_LOGOUT_T(R7) ; EFFECTIVE LOGOUT TIME PUSHL R8 ; UPDATE TT CONN USAGE CALLS #1,TTCONNUPD RSB_LOGOUT: MOVL R11,ARG_REPLY ; ADR BUFBLK FOR REPLY JSB PROC_REPLY ; SPEAK TO THE PEOPLE! INSQUE (R11),@FREE_BUFBLK+4 ; RETURN TASK BUFBLK TO POOL POPR #MASK_LOGOUT ; RESTORE WORK REGS RSB .PAGE .SBTTL PROC_ALTER ; THIS ROUTINE ALTERS PARAMETERS IN AN EXISTING PRCS. ; CURRENTLY IT ONLY REPLACES A LONGWORD DATA ITEM. MASK_ALTER= ^M PROC_ALTER: PUSHR #MASK_ALTER ; SAVE WORK REGS MOVAB BFB_BUFR(R11),R10 ; ADR OF ALTER DATA MOVQ #SS$_NORMAL,STS_REPLY ; INIT SUCCESS STATUS MOVL BFB_IOSB+4(R11),PID ; FIND PRCS MOVAB PRCS_USERNAME(R10),ADR_USERNAME JSB PROC_FIND MOVL ADR_PRCS,R8 ; ADR PRCS BNEQ 10$ CLRQ STS_REPLY ; ERROR -- PRCS NOT FOUND $PUTMSG_S MSGVEC=MSG_NOSUCHPRC,- ; GENERATE ERROR MSG ACTRTN=MSGACTRTN,- ACTPRM=#0 MOVC3 #REPLY_K_LENTXT,STRG_MSGTXT,- ; INSERT MSGTXT FOR REPLY BUFR_REPLY+REPLY_MSGTXT BRW RSB_ALTER 10$: MOVAB BFB_BUFR(R8),R6 ; ADR PRCS DATA ADDL PRCS_ALTOFFSET(R10),R6 ; ADR ITEM TO ALTER MOVL PRCS_ALTDATA(R10),(R6) ; REPLACE ITEM RSB_ALTER: MOVL R11,ARG_REPLY ; SEND REPLY JSB PROC_REPLY INSQUE (R11),@FREE_BUFBLK+4 ; RELEASE ALTER BUFBLK POPR #MASK_ALTER ; RESTORE WORK REGS RSB .PAGE .SBTTL PROC_DELPROC ; THIS ROUTINE DELETES PROCESSES FROM ISUQUOTA USING DATA SENT THROUGH ; ISUMONMBX BY SYS$DELPROC. ; IF THE PROCESS WENT THROUGH ISULOGOUT THEN THE PRCS AND ACCOUNTING ; RECORD ARE RELEASED. OTHERWISE, TT CONNECT TIME IS UPDATED FOR IAC ; PRCS, THE USERNAME IS UNLOCKED AND THE FAILURE LOGGED FOR DEFERRED ; LOGOUT PRCS, AND THE PRCS IS MARKED AS BYPASS-LOGOUT. ; ACCOUNTING IS QUEUED FOR ALL PRCS WHICH DID NOT GO THROUGH ISULOGUT. ; THE PRCS IS REMOVED, BUT BYPASS-LOGOUT PRCS ARE RECOVERED AND A ; DEFERRED-LOGOUT PRCS IS QUEUED FOR IT. MASK_DELPROC= ^M PROC_DELPROC: PUSHR #MASK_DELPROC ; SAVE WORK REGS MOVB #1,FLG_DO_ACCTG ; ENABLE ACCTG MOVAB BFB_BUFR(R11),R10 ; R10= ADR ACCTG RECORD MOVAB ACC$T_USERNAME(R10),ADR_USERNAME ; FIND PRCS BUFBLK MOVL ACC$L_PID(R10),PID JSB PROC_FIND MOVL ADR_PRCS,R9 ; ADR PRCS BUFBLK BEQL DELPROC_ACCTG ; UNKNOWN PRCS MOVAB BFB_BUFR(R9),R8 ; ADR PRCS DATA BITL #PRCS_M_DLO,PRCS_TYPE(R8) ; DEFERRED LOGOUT? BEQL 5$ ; NO MOVL R9,ARG_UNLOCK ; UNLOCK USER JSB PROC_UNLOCK 5$: MOVQ ACC$Q_TERMTIME(R10),PRCS_LOGOUT_T(R8) ; SET LOGOUT TIME BITL #PRCS_M_LOGOUT,PRCS_STATE(R8) ; BYPASS ISULOGOUT? BEQL 10$ ; YES CLRB FLG_DO_ACCTG ; TURN OFF ACCTG INSQUE (R11),@FREE_BUFBLK+4 ; RLSE ACCTG RECORD BRW DELPROC_ACCTG 10$: BITL #PRCS_M_IAC,PRCS_TYPE(R8) ; INTERACTIVE PRCS? BEQL 20$ ; NO PUSHL R9 ; UPDATE TT CONN USAGE CALLS #1,TTCONNUPD 20$: BITL #PRCS_M_DLO,PRCS_TYPE(R8) ; DEFERRED LOGOUT PRCS? BEQL 30$ ; NO JSB PROC_DFRLOFAIL ; UNLOCK USER AND LOG FAILURE BRB DELPROC_ACCTG 30$: BITL #QMSK_M_BYPASLO,PRCS_QMASK(R8) ; BYPASS LOGOUT ENABLED? BEQL DELPROC_ACCTG ; NO MOVL #PRCS_M_BYPASLO,PRCS_STATE(R8) ; MARK PRCS BYPASSED ISULOGOUT DELPROC_ACCTG: BLBC FLG_DO_ACCTG,DELPROC_REMPRCS ; IF DISABLED ACCTG THEN SKIP REMQUE @FREE_MISCTSK,R7 ; GET MTSK FOR DEFERRED ACCTG BVC 10$ MOVAQ DSC_FREEMTSK,ARG_EMPTYQUE ; LOG FREE_MISCTSK QUEUE EMPTY JSB PROC_LOGMPTYQUE BRW DELPROC_REMPRCS 10$: MOVW #MTSK_K_ACCTG,MTSK_TYPE(R7) ; INIT ACCTG MISCELLANEOUS TASK MOVW MAX_ACCRETRY,MTSK_TALLY(R7) CLRL MTSK_CONN(R7) MOVL R11,MTSK_ADR(R7) TSTL R9 ; KNOWN PRCS TYPE? BNEQ 13$ ; YES CLRL MTSK_ACCTYPE(R7) BRB 15$ 13$: MOVL PRCS_TYPE(R8),MTSK_ACCTYPE(R7) 15$: INSQUE (R7),@QHD_MISCTSK+4 ; QUEUE DEFERRED ACCTG TASK DELPROC_REMPRCS: MOVL R9,ARG_REMPRCS ; REMOVE PRCS BEQL RSB_DELPROC ; NONE TO REMOVE JSB PROC_REMPRCS BITL #PRCS_M_BYPASLO,PRCS_STATE(R8) ; WAS IT A BYPASS-LOGOUT PRCS? BEQL RSB_DELPROC ; NO REMQUE @FREE_MISCTSK,R7 ; GET MTSK FOR DEFERRED LOGOUT BVC 10$ MOVAQ DSC_FREEMTSK,ARG_EMPTYQUE ; LOG FREE_MISCTSK QUEUE EMPTY JSB PROC_LOGMPTYQUE BRW RSB_DELPROC 10$: MOVW #MTSK_K_DFRLO,MTSK_TYPE(R7) ; INIT MTSK TYPE MOVL EXT_BYPASLO,MTSK_CONN(R7) CLRW MTSK_TALLY(R7) REMQUE (R9),MTSK_ADR(R7) ; RECOVER BYPASLO PRCS MOVL MTSK_ADR(R7),R6 ; CLEAR DFRLO PID CLRL BFB_IOSB+4(R6) INSQUE (R7),@QHD_MISCTSK+4 ; QUEUE DEFRLO TASK RSB_DELPROC: POPR #MASK_DELPROC ; RESTORE WORK REGS RSB .PAGE .SBTTL PROC_TIMER ; THIS ROUTINE IS ACTIVATED AT REGULAR INTERVALS BY A TIMER. IT SCANS ; ALL PRCS QUEUES AND DECREMENTS THE CONNECT TIME COUNTER FOR ALL ; INTERACTIVE PROCESSES. IF THE CONNECT TIMER EXPIRES THE ENTRY IS ; PROCESSED ACCORDING TO ITS STATE: ; 1. LOGIN - WARNING $BRDCST TO TERMINAL, ENTRY MARKED ; WARNED, AND CONNECT TIME EXTENDED. ; 2. WARNED - BYE-BYE MSG $BRDCST TO TERMINAL, ENTRY ; MARKED KILLED, AND PROCESS DELETED. ; 3. BYPASS - CONTINUE UNTIL NO OTHER PROCESS FOR THIS ; USER. THEN LOCK USER AND CREATE PROCESS ; TO PERFORM LOGOUT FUNCTIONS. MASK_TIMER= ^M PROC_TIMER: PUSHR #MASK_TIMER ; SAVE WORK REGS INSQUE (R11),@FREE_BUFBLK+4 ; RLSE TIMER TASK MOVAQ QHD_USER,R6 ; BEGIN USER QUEUE LOOP_SCANUSER: MOVL (R6),R6 ; NEXT USER ENTRY CMPL R6,#QHD_USER ; DO UNTIL END_QUEUE BNEQ 10$ BRW RSB_TIMER 10$: MOVL R6,ADR_USER ; CURRENT USER ENTRY ADR MOVAQ USER_QHD_PRCS(R6),R7 ; BEGIN PROCESS QUEUE MOVL R7,R9 ; R9= ADR END_QUEUE LOOP_SCANPRCS: MOVL (R7),R7 ; NEXT PRCS ENTRY CMPL R7,R9 ; DO UNTIL END_QUEUE BNEQ 10$ BRW CONT_SCANUSER 10$: MOVAB BFB_BUFR(R7),R8 ; R8= ADR PRCS ENTRY BUFFER MOVL R7,ADR_PRCS ; CURRENT PRCS ENTRY ADR BITL #QMSK_M_CONN,PRCS_QMASK(R8) ; CONN ENFORCED? BEQL CONT_SCANPRCS ; NO SUBL DELTA_CONN,PRCS_CONN(R8) ; DECR CONNECT TIME QUOTA BGTR CONT_SCANPRCS BITL PRCS_STATE(R8),#PRCS_M_LOGIN ; FIRST TIME WARNING BEQL 20$ MOVL #ISUQUO_CONNEXT,MSGID_SNDTT ; SET UP TO BCAST WARNING DIVL3 #60,EXT_CONN,ALST_SNDTT_FAOL ; CVT EXTEND TIME TO MINUTES JSB PROC_SNDTT ; BROADCAST WARNING MOVL EXT_CONN,PRCS_CONN(R8) ; SET EXTENDED CONNECT TIME MOVL #PRCS_M_WARNED,PRCS_STATE(R8) ; MARK PRCS WARNED BRW CONT_SCANPRCS 20$: BITL #PRCS_M_WARNED,PRCS_STATE(R8) ; SECOND TIME KILL PRCS BEQL 30$ MOVL #ISUQUO_CONNDEL,MSGID_SNDTT ; SET UP TO BCAST THE BAD NEWS JSB PROC_SNDTT ; "...FOR WHOM THE BELL TOLLS.. $DELPRC_S PIDADR=BFB_IOSB+4(R7) ; ZAP-ZAP BLBC R0,CONT_SCANPRCS ; TRY AGAIN, AND AGAIN, AND ... MOVL #PRCS_M_KILLED,PRCS_STATE(R8) ; MARK PRCS CANCELED BRW CONT_SCANPRCS 30$: CONT_SCANPRCS: BRW LOOP_SCANPRCS CONT_SCANUSER: BRW LOOP_SCANUSER RSB_TIMER: JSB PROC_MISCTSK ; DO MISCELLANEOUS CYCLIC TASKS POPR #MASK_TIMER ; RESTORE WORK REGISTERS RSB .PAGE .SBTTL PROC_MISCTSK ; MASK_MISCTSK= ^M PROC_MISCTSK: PUSHR #MASK_MISCTSK MOVAQ QHD_MISCTSK,R6 ; LOOP INDEX LOOP_MISCTSK: MOVL (R6),R6 ; LINK TO NEXT TASK CMPL R6,#QHD_MISCTSK ; DONE? BEQL RSB_MISCTSK ; YES CASEW MTSK_TYPE(R6),#1,#2$-1$/2-1 1$: .WORD MISCTSK_ACCTG-1$ .WORD MISCTSK_DFRLO-1$ 2$: MOVW MTSK_TYPE(R6),MSG_BADMTSK+QMSG_FAO_ARG+4 $PUTMSG_S MSGVEC=MSG_BADMTSK JMP MISCTSK_RELEASE MISCTSK_ACCTG: JSB PROC_MTSKACCTG ; DO ACCOUNTING BLBS R0,MISCTSK_RELEASE ; SUCCESS BRW CONT_MISCTSK MISCTSK_DFRLO: SUBL DELTA_CONN,MTSK_CONN(R6) ; TIME FOR DEFERRED LOGOUT? BGTR CONT_MISCTSK ; NO JSB PROC_MTSKDFRLO ; CREATE DEFERRED LOGOUT PRCS BRW CONT_MISCTSK MISCTSK_RELEASE: TSTL MTSK_ADR(R6) ; BUFBLK TO RELEASE? BEQL 10$ ; NO INSQUE @MTSK_ADR(R6),@FREE_BUFBLK+4 ; RELEASE DEFERRED BUFBLK 10$: MOVL MTSK_BLINK(R6),R6 ; BACK UP TO PRED MISC TASK REMQUE @MTSK_FLINK(R6),R10 ; RELEASE MISC TASK INSQUE (R10),@FREE_MISCTSK+4 CONT_MISCTSK: BRW LOOP_MISCTSK RSB_MISCTSK: POPR #MASK_MISCTSK RSB .PAGE .SBTTL PROC_MTSKACCTG ; PROC_MTSKACCTG: MOVL R6,ARG_ACCTG ; ADR ACCTG MISC TASK JSB PROC_ACCTG ; DO ACCTG BLBS R0,RSB_MTSKACCTG ; SUCCESS DECW MTSK_TALLY(R6) ; DECR ATTEMPT COUNT BLEQ 10$ ; NO MORE ATTEMPTS JMP RSB_MTSKACCTG ; KEEP TRYING 10$: MOVL MTSK_ADR(R6),R7 ; ADR BUFBLK FOR ACCTG RECORD MOVAB BFB_BUFR(R7),R8 ; ADR ACCTG DATA TSTW PRCS_TYPE+2(R8) ; ISU MSG? BNEQ 20$ ; YES PUSHAB ACC$T_USERNAME ; GENERATE USERNAME DESCRIPTOR BRW 22$ 20$: PUSHAB PRCS_USERNAME(R8) 22$: PUSHL #QXR_K_LENUSRNAM MOVAB MSG_ACCFAIL+QMSG_FAO_ARG+4,R9 ; ADR MSG FAO ARGS MOVL SP,(R9)+ MOVL R0,(R9)+ $PUTMSG_S MSGVEC=MSG_ACCFAIL ; LOG ERROR MOVAB 8(SP),SP ; RELEASE USERNAME DESCRIPTOR MOVL #1,R0 ; FORCE DELETE MTSK RSB_MTSKACCTG: RSB .PAGE .SBTTL PROC_MTSKDFRLO ; MASK_MTSKDFRLO= ^M PROC_MTSKDFRLO: PUSHR #MASK_MTSKDFRLO ; SAVE WORK REGS MOVL MTSK_ADR(R6),R11 ; ADR PRCS BUFBLK TSTL BFB_IOSB+4(R11) ; DFRLO ALREADY CREATED? BEQL 5$ ; NO JMP RSB_MTSKDFRLO 5$: MOVAB BFB_BUFR(R11),R10 ; ADR PRCS DATA CLRL PID ; FIND USER MOVAB PRCS_USERNAME(R10),ADR_USERNAME JSB PROC_FIND TSTL ADR_USER ; IF USERNAME ACTIVE THEN WAIT BNEQ 10$ REMQUE @FREE_USER,R9 ; GET USER ENTRY BVC 20$ MOVAQ DSC_FREEUSER,ARG_EMPTYQUE ; LOG FAILURE JSB PROC_LOGMPTYQUE 10$: CLRL R0 ; FAILURE STATUS MOVL EXT_BYPASLO,MTSK_CONN(R6) ; TRY AGAIN LATER BRW RSB_MTSKDFRLO 20$: MOVL #USER_M_LOCK,USER_FLAGS(R9) ; INIT USER ENTRY MOVC3 #QXR_K_LENUSRNAM,PRCS_USERNAME(R10),USER_USERNAME(R9) MOVL PRCS_UIC(R10),USER_UIC(R9) MOVL #1,USER_COUNT(R9) CLRL USER_CNT_IAC(R9) MOVAQ USER_QHD_PRCS(R9),USER_QHD_PRCS(R9) MOVAQ USER_QHD_PRCS(R9),USER_QHD_PRCS+4(R9) INSQUE (R9),@QHD_USER+4 ; INSERT USERNAME ON USER QUEUE INSQUE (R11),@USER_QHD_PRCS+4(R9) ; INIT PRCS ENTRY FOR DFRLO MOVL #PRCS_M_DLO,PRCS_TYPE(R10) ; (USE OLD BYPASLO ENTRY) MOVL #PRCS_M_LOGIN,PRCS_STATE(R10) BICL #QMSK_M_CONN,PRCS_QMASK(R10) ; NO CONN LIMIT MOVL R9,BFB_ADRUSER(R11) $CREPRC_S PIDADR=BFB_IOSB+4(R11),- ; CREATE DEFERRED IMAGE=DSC_ISULOGOUT,- ; LOGOUT PROCESS. INPUT=DSC_NLA0,- OUTPUT=DSC_NLA0,- ERROR=DSC_NLA0,- PRVADR=PRV_DFRLO,- BASPRI=#4,- UIC=PRCS_UIC(R10),- MBXUNT=UNIT_DLOMBX BLBS R0,RSB_MTSKDFRLO MOVAL MSG_NODFRLO+QMSG_FAO_ARG+4,R8 ; LOG FAILURE ERROR PUSHAB PRCS_USERNAME(R10) PUSHL #QXR_K_LENUSRNAM MOVL SP,(R8)+ MOVL R0,(R8)+ $PUTMSG_S MSGVEC=MSG_NODFRLO MOVAB 8(SP),SP ; RLSE WORK AREA MOVL R11,ARG_REMPRCS ; DELETE PRCS JSB PROC_REMPRCS MOVL #1,R0 ; FORCE MTSK RELEASE RSB_MTSKDFRLO: POPR #MASK_MTSKDFRLO ; RESTORE WORK REGS RSB .PAGE .SBTTL PROC_DFRLOFAIL ; MASK_DFRLOFAIL= ^M PROC_DFRLOFAIL: PUSHR #MASK_DFRLOFAIL ; SAVE WORK REGS MOVAL MSG_DFRLOFAIL+QMSG_FAO_ARG,R6 ; ADR MSGVEC ARGS MOVAB PRCS_USERNAME(R8),-(SP) ; GENERATE USERNAME DESCRIPTOR MOVL #QXR_K_LENUSRNAM,-(SP) CLRL (R6)+ MOVL SP,(R6)+ MOVL ACC$L_FINALSTS(R10),(R6)+ $PUTMSG_S MSGVEC=MSG_DFRLOFAIL ; LOG ERROR MOVAB 8(SP),SP ; RLSE WORK AREA RSB_DFRLOFAIL: POPR #MASK_DFRLOFAIL ; RESTORE WORK REGS RSB .PAGE .SBTTL PROC_ACCTG MASK_ACCTG= ^M PROC_ACCTG: PUSHR #MASK_ACCTG ; SAVE WORK REGS MOVL #1,R0 ; INIT SUCCESS STATUS MOVL ARG_ACCTG,R7 ; ADR MTSK MOVL MTSK_ADR(R7),R11 ; ACCTG BUFBLK MOVAB BFB_BUFR(R11),R10 ; ADR ACCOUNTING DATA MOVAL TAB_ACCFACTR,R9 ; ADR ACCTG FACTORS TABLE MOVC5 #0,(R9),#0,#AFACTR_L,(R9) ; CLEAR AFACTR TABLE TSTW PRCS_TYPE+2(R10) ; CHK ISUMONMBX RECORD TYPE BEQL ACCTG_PRCS ; DEC $DELPROC RECORD ACCTG_PRINT: $RAB_STORE RAB=RAB_QUAX,- ; INIT KEY THIS USERNAME KRF=#0,- KSZ=#QXR_K_LENUSRNAM,- KBF=PRCS_USERNAME(R10) $GET RAB=RAB_QUAX ; GET QUAX RECORD BLBS R0,10$ JMP RSB_ACCTG ; ERROR RETURN 10$: MOVL PRCS_SMBPAGECNT(R10),AFACTR_PAGCNT(R9) ; SET PAGECNT FOR ACCTG MOVC3 #16,PRCS_SMBQUENAM(R10),ACC_QUENAM ; SET QUEUE NAME CLRL -(SP) PUSHAB QUAX ; UPDATE QUAX USAGE/COSTS PUSHAL (R9) PUSHAL PRCS_TYPE(R10) PUSHAQ PRCS_SMBTIME(R10) CALLS #5,G^ISUACCTG JMP ACCTG_WRTLOG ACCTG_PRCS: MOVC5 #0,(R9),#^A\ \,#11,ACC_QUENAM+1 ; NULL QUEUE NAME FIELD CLRB ACC_QUENAM $RAB_STORE RAB=RAB_QUAX,- ; SET USERNAME KEY KRF=#0,- KSZ=#QXR_K_LENUSRNAM,- KBF=ACC$T_USERNAME(R10) $GET RAB=RAB_QUAX ; GET QUAX RECORD BLBS R0,10$ JMP RSB_ACCTG ; ERROR RETURN 10$: CMPL MTSK_ACCTYPE(R7),#PRCS_M_IAC ; IF PRCS IS INTERACTIVE THEN BNEQ 20$ ; COMPUTE THE CONNECT TIME. CLRQ -(SP) ; WORK AREA SUBQ3 ACC$Q_LOGIN(R10),ACC$Q_TERMTIME(R10),0(SP) ; DELTA CONN EDIV #10000000,(SP),(SP),4(SP) ; CVT TO LONG WORD AND ENTER MOVL (SP),AFACTR_CONN(R9) ; INTO ACCTG FACTOR TABLE. MOVAB 8(SP),SP ; RLSE WORK AREA 20$: MOVL ACC$L_CPUTIM(R10),AFACTR_CPU(R9) ; FILL IN OTHER FACTORS MOVL ACC$L_DIOCNT(R10),AFACTR_DIOCNT(R9) CLRL -(SP) ; UPDATE QUAX USAGE/COSTS PUSHAB QUAX PUSHAL (R9) TSTL MTSK_ACCTYPE(R7) ; IF UNKNOWN PRCS THEN NO PRCS BNEQ 30$ ; TYPE. CLRL -(SP) BRB 31$ 30$: PUSHAL MTSK_ACCTYPE(R7) 31$: PUSHAQ ACC$Q_LOGIN(R10) CALLS #5,G^ISUACCTG ACCTG_WRTLOG: MOVQ ACC$Q_LOGIN(R10),LOGIN_TIME ; FILL IN ACCTG LOG RECORD MOVC3 #12,ACC$T_USERNAME(R10),USERNAME MOVL QUAX+QXR_UIC,UIC MOVC3 #8,ACC$T_ACCOUNT(R10),ACCOUNT $SNDACC_S MSGBUF=DSC_WRTLOG_ACC ; LOG ACCOUNTING INFO ACCTG_UPDQUAX: $UPDATE RAB=RAB_QUAX ; UPDATE/RELEASE QUAX RECORD RSB_ACCTG: POPR #MASK_ACCTG ; RESTORE WORK REGS RSB .PAGE .SBTTL PROC_SNDTT ; MASK_SNDTT= ^M PROC_SNDTT: PUSHR #MASK_SNDTT ; SAVE WORK REGS MOVL ADR_PRCS,R8 ; ADR PRCS ENTRY MOVAB BFB_BUFR(R8),R8 ; ADR PRCS DATA CMPL PRCS_TYPE(R8),#PRCS_M_IAC ; INTERACTIVE PRCS? BNEQ RSB_SNDTT ; NO SUBL #132,SP ; WORK AREA MOVL SP,R6 CLRL (R6) ; LEN MSG TEXT MOVL #120,4(R6) ; DESCRIPTOR MSG TEXT MOVAB 12(R6),8(R6) $GETMSG_S MSGID=MSGID_SNDTT,- ; GET MSG STRING MSGLEN=(R6),- BUFADR=4(R6) BLBC R0,10$ ; IGNORE ERRORS MOVL (R6),4(R6) ; UPDATE MSG STRG DESCRIPTOR $FAOL_S CTRSTR=4(R6),- ; GENERATE MESSAGE OUTLEN=DYN_MSG_SNDTT,- OUTBUF=DSC_MSG_SNDTT,- PRMLST=ALST_SNDTT_FAOL BLBC R0,10$ ; IBID MOVZBL PRCS_TTNAME(R8),(R6) ; TERMINAL NAME DESCRIPTOR MOVAB PRCS_TTNAME+1(R8),4(R6) $BRDCST_S MSGBUF=DYN_MSG_SNDTT,- ; "HEAR YE! HEAR YE! ..." DEVNAM=(R6) 10$: MOVAB 132(SP),SP ; RLSE WORK AREA RSB_SNDTT: POPR #MASK_SNDTT ; RESTORE WORK REGS RSB .PAGE .SBTTL PROC_REPLY ; THIS ROUTINE RETURNS ISUMONITR INFORMATION TO THE USER MAILBOX. ; IT ENABLES AN AST FOR I/O COMPLETION IN ORDER TO RELEASE THE CHANNEL ; AND BUFFER BLOCK. MASK_REPLY= ^M PROC_REPLY: PUSHR #MASK_REPLY ; SAVE WORK REGS MOVL ARG_REPLY,R7 ; ADR BUFR BLK MOVAB BFB_BUFR(R7),R8 ; ADR CURRENT PRCS ENTRY TSTB PRCS_UMBXNAM(R8) ; IF NO UMBX THEN RETURN BNEQ 10$ JMP RSB_REPLY 10$: MOVAB BUFR_REPLY,R6 ; ADR REPLY BUFFER REPLY_FILL: MOVQ STS_REPLY,REPLY_STATUS(R6) ; FILL IN REPLY MSG MOVC3 #QXR_K_LENUSRNAM,PRCS_USERNAME(R8),REPLY_USERNAME(R6) MOVL PRCS_UIC(R8),REPLY_UIC(R6) BLBC STS_REPLY,10$ ; IF FAIL THEN SKIP FILL MOVL PRCS_CONN(R8),REPLY_CONN_S(R6) MOVQ PRCS_RESET_T(R8),REPLY_RESET_T(R6) CLRL REPLY_CNT_IAC(R6) ; INIT IAC COUNT MOVL BFB_ADRUSER(R7),R5 ; ADR USER DATA BEQL 10$ ; IN CASE IT AINT THERE MOVL USER_CNT_IAC(R5),REPLY_CNT_IAC(R6) MOVL GBL_COUNT_IAC,REPLY_TOTAL_IAC(R6) 10$: MOVZBL PRCS_UMBXNAM(R8),DYN_UMBXNAM ; INIT UMBX NAME DESCRIPTOR MOVAB PRCS_UMBXNAM+1(R8),DYN_UMBXNAM+4 $ASSIGN_S CHAN=CHAN_REPLY,- ; GET CHANNEL TO UMBX DEVNAM=DYN_UMBXNAM BLBC R0,REPLY_QIOERR ; FAILED $QIOW_S CHAN=CHAN_REPLY,- ; SEND IT AND FORCE IMMEDIATE FUNC=#IO$_WRITEVBLK!IO$M_NOW,- ; I/O COMPLETION P1=BUFR_REPLY,- P2=#REPLY_K_LENGTH BLBS R0,REPLY_DASSGN REPLY_QIOERR: MOVAL WORK,R6 ; LOG ERROR MOVL #5,QMSG_LENGTH(R6) MOVL #ISUQUO_NOREPLY,QMSG_MSGID(R6) MOVL #3,QMSG_FAO_CNT(R6) MOVAL QMSG_FAO_ARG(R6),R6 CLRL (R6)+ PUSHAB PRCS_USERNAME(R8) PUSHL #QXR_K_LENUSRNAM MOVL SP,(R6)+ MOVAB 8(SP),SP ; RLSE WORK AREA MOVL R0,(R6)+ ELOG_NORPLY_1: $PUTMSG_S MSGVEC=WORK REPLY_DASSGN: $DASSGN_S CHAN=CHAN_REPLY RSB_REPLY: POPR #MASK_REPLY RSB .PAGE .SBTTL PROC_ABORTDFRLO ; THIS ROUTINE SCANS THE MISCTSK QUEUE FOR ALL DEFERRED-LOGOUT TASKS WHICH ; BELONG TO THE CURRENT PRCS_UIC, AND REMOVES THEM. MASK_ABORTDFRLO= ^M PROC_ABORTDFRLO: PUSHR #MASK_ABORTDFRLO ; SAVE WORK REGS MOVL ADR_USER,R10 ; ADR USER ENTRY BEQL RSB_ABORTDFRLO MOVAQ QHD_MISCTSK,R6 ; LOOP INDEX LOOP_ABORTDFRLO: MOVL (R6),R6 ; LINK TO NEXT QUEUE ENTRY CMPL R6,#QHD_MISCTSK ; DONE? BEQL RSB_ABORTDFRLO ; YES CMPW MTSK_TYPE(R6),#MTSK_K_DFRLO ; BYPASS LOGOUT PENDING? BNEQ CONT_ABORTDFRLO ; NO MOVL MTSK_ADR(R6),R9 ; GET PRCS ADR MOVAB BFB_BUFR(R9),R8 CMPL PRCS_UIC(R8),USER_UIC(R10) ; SAME USER? BNEQ CONT_ABORTDFRLO ; NO TSTL BFB_IOSB+4(R9) ; DEFERRED LOGOUT ACTIVE? BNEQ CONT_ABORTDFRLO ; YES INSQUE (R9),@FREE_BUFBLK+4 ; RLSE PENDING BYPASLO PRCS MOVL MTSK_BLINK(R6),R6 ; BACK-UP TO PRED MISC TASK REMQUE @MTSK_FLINK(R6),R8 ; RLSE MISC TASK INSQUE (R8),@FREE_MISCTSK+4 CONT_ABORTDFRLO: BRW LOOP_ABORTDFRLO RSB_ABORTDFRLO: POPR #MASK_ABORTDFRLO ; RESTORE WORK REGS RSB .PAGE .SBTTL PROC_UNLOCK ; MASK_UNLOCK= ^M PROC_UNLOCK: PUSHR #MASK_UNLOCK ; SAVE WORK REGS MOVL ADR_USER,R9 ; ADR USER BEQL RSB_UNLOCK ; PROTECT AGAINST ACCVIO BICL #USER_M_LOCK,USER_FLAGS(R9) ; UNLOCK USERNAME MOVAQ USER_QHD_PRCS(R9),R7 ; LOOP TO SEND ALL PENDING MOVL R7,R6 ; REPLIES LOOP_UNLOCK: MOVL (R6),R6 ; LINK TO NEXT PRCS CMPL R6,R7 ; DONE? BEQL RSB_UNLOCK ; YES MOVAB BFB_BUFR(R6),R8 ; ADR PRCS DATA BBCC #PRCS_V_RPLYPND,PRCS_STATE(R8),- ; IF REPLY PENDING THEN CONT_UNLOCK ; SEND IT MOVL R6,ARG_REPLY JSB PROC_REPLY CONT_UNLOCK: BRW LOOP_UNLOCK RSB_UNLOCK: POPR #MASK_UNLOCK ; RESTORE WORK REGS RSB .PAGE .SBTTL PROC_FIND ; THIS ROUTINE LOCATES USER AND PRCS QUEUE ENTRIES FOR CURRENT ; PROCESS (VALUES STORED IN PID AND USERNAME). ENTRY ADRESSES ARE ; STORED IN ADR_USER AND ADR_PRCS. MASK_FIND= ^M PROC_FIND: PUSHR #MASK_FIND ; SAVE WORK REGS CLRL ADR_USER CLRL ADR_PRCS MOVAQ QHD_USER,R6 ; BEGIN USER QUEUE FIND_USER: MOVL (R6),R6 ; NEXT USER ENTRY CMPL R6,#QHD_USER ; DO UNTIL END_QUEUE BEQL RSB_FIND CMPC3 #QXR_K_LENUSRNAM,@ADR_USERNAME,- ; THIS USERNAME? USER_USERNAME(R6) BNEQ FIND_USER ; NO MOVL R6,ADR_USER ; YES MOVAQ USER_QHD_PRCS(R6),R7 ; BEGIN PRCS QUEUE MOVL R7,R8 ; ADR END_QUEUE FIND_PRCS: MOVL (R7),R7 ; NEXT PRCS ENTRY CMPL R7,R8 ; DO UNTIL END_QUEUE BEQL RSB_FIND CMPL PID,BFB_IOSB+4(R7) ; FIND THIS PROCESS? BNEQ FIND_PRCS ; NO MOVL R7,ADR_PRCS ; YES RSB_FIND: POPR #MASK_FIND ; RESTORE WORK REGISTERS RSB .PAGE .SBTTL PROC_REMPRCS ; THIS ROUTINE REMOVES THE CURRENT PROCESS FROM ITS PRCS QUEUE (VALUE ; STORED IN ADR_PRCS), AND SETS ADR_PRCS TO THE PREDECESSOR PRCS ENTRY. ; IF THE PRCS QUEUE BECOMES EMPTY THE USER QUEUE ENTRY IS ALSO REMOVED, ; ADR_USER IS SET TO THE PREDECESSOR USER ENTRY AND ADR_PRCS IS SET TO ; THE LAST ENTRY IN THAT USER'S PRCS QUEUE OR ZERO (IF USER QUEUE IS ; EMPTY). MASK_REMPRCS= ^M PROC_REMPRCS: PUSHR #MASK_REMPRCS ; SAVE WORK REGS MOVL ADR_PRCS,R8 ; PRCS TO REMOVE BNEQ 10$ ; IGNORE NON-EXISTENT PRCS JMP RSB_REMPRCS 10$: MOVAB BFB_BUFR(R8),R7 ; ADR PRCS DATA MOVL BFB_ADRUSER(R8),R6 ; USER PARENT BNEQ REMPRCS_DECNT MOVAL WORK,R6 ; SOMETHING SCREWY -- LOG ERROR MOVL #6,QMSG_LENGTH(R6) MOVL #ISUQUO_BADQUE,QMSG_MSGID(R6) MOVL #4,QMSG_FAO_CNT(R6) MOVAL QMSG_FAO_CNT(R6),R6 CLRL (R6)+ MOVAL ELOG_BADQUE,(R6)+ MOVL #QXR_K_LENUSRNAM,(R6)+ MOVAB PRCS_USERNAME(R7),(R6)+ ELOG_BADQUE: $PUTMSG_S MSGVEC=WORK BRW REMPRCS_ENTRY REMPRCS_DECNT: DECL USER_COUNT(R6) ; DECR ACTIVE PRCS COUNT BITL #PRCS_M_IAC,PRCS_TYPE(R7) ; INTERACTIVE PRCS? BEQL REMPRCS_ENTRY ; NO DECL USER_CNT_IAC(R6) ; DECR IAC COUNT DECL GBL_COUNT_IAC ; DECR TOTAL IAC PRCS COUNT REMPRCS_ENTRY: REMQUE (R8),R8 ; REMOVE PRCS ENTRY BNEQ 20$ ; PRCS QUEUE EMPTY? INSQUE (R8),@FREE_BUFBLK+4 ; YES, RETURN PRCS BUFBLK TO POOL REMQUE (R6),R6 ; REMOVE USER ENTRY BNEQ 10$ ; USER QUEUE EMPTY? INSQUE (R6),@FREE_USER+4 ; YES, RETURN USER ENTRY TO POOL CLRL ADR_USER CLRL ADR_PRCS BRW RSB_REMPRCS 10$: MOVL USER_BLINK(R6),ADR_USER ; SET CURRENT USER TO PRED USER INSQUE (R6),@FREE_USER+4 ; RETURN USER BUFBLK TO POOL MOVL ADR_USER,R6 ; NEW CURRENT USER MOVL USER_QHD_PRCS+4(R6),ADR_PRCS ; CURRENT PRCS AT END_QUEUE BRW RSB_REMPRCS 20$: MOVL BFB_BLINK(R8),ADR_PRCS ; CURRENT PRCS IS PRED PRCS INSQUE (R8),@FREE_BUFBLK+4 ; RETURN PRCS BUFBLK TO POOL RSB_REMPRCS: POPR #MASK_REMPRCS ; RESTORE WORK REGISTERS RSB .PAGE .SBTTL PROC_INIT ; THIS ROUTINE CREATES MAILBOXES, OPENS FILES, AND CREATES QUEUES. ; AFTER INITIALIZATION IT LOGS START TIME IN ERROR LOG AND NOTIFIES THE ; OPERATOR ISUMONITR HAS RESTARTED. ; IF ANYTHING FAILS DURING INITIALIZATION THE ERROR IS LOGGED, THE OPERATOR ; IS NOTIFIED, AND THE PROGRAM EXITS WITH ERROR CODE. PROC_INIT: $CREMBX_S CHAN=CHAN_MONMBX,- ; CREATE ISUMONMBX PRMFLG=#1,- MAXMSG=#BFB_K_BUFLEN,- BUFQUO=#25*BFB_K_BUFLEN,- LOGNAM=DSC_ISUMONMBX JSB PROC_ERREXIT $CANCEL_S CHAN=CHAN_MONMBX ; PURGE OLD MBX I/O $CREMBX_S CHAN=CHAN_DLOMBX,- ; CREATE ISUDLOMBX PRMFLG=#1,- MAXMSG=#BFB_K_BUFLEN,- BUFQUO=#5*BFB_K_BUFLEN,- LOGNAM=DSC_ISUDLOMBX JSB PROC_ERREXIT $CREATE FAB=FAB_ERROR ; OPEN SYS$ERROR JSB PROC_ERREXIT $CONNECT RAB=RAB_ERROR JSB PROC_ERREXIT $OPEN FAB=FAB_QUAX ; OPEN QUAX FILE JSB PROC_ERREXIT $CONNECT RAB=RAB_QUAX CALLS #0,TTCONNINI ; INITIALIZE TTCONN FILE JSB PROC_ERREXIT INIT_QUEUES: INIQUE QHD=FREE_USER,- ; CREATE USER QUEUE POOL NUM=#N_USER,- LEN=#USER_K_LENGTH JSB PROC_ERREXIT INIQUE QHD=FREE_BUFBLK,- ; CREATE BUFBLK POOL NUM=#N_BUFBLK,- LEN=#BFB_K_LENGTH JSB PROC_ERREXIT INIQUE QHD=FREE_MISCTSK,- ; CREATE MISC TASK QUEUE NUM=#N_MISCTSK,- LEN=#MTSK_K_LENGTH $SETIMR_S DAYTIM=DELTA_T,- ; START MONITOR TIMER ASTADR=ASTMONITR,- REQIDT=#3 JSB PROC_ERREXIT $QIOW_S CHAN=CHAN_MONMBX,- ; SET WRITE ATTN ON ISUMONMBX FUNC=#IO$_SETMODE!IO$M_WRTATTN,- P1=ASTMONITR,- P2=#1 JSB PROC_ERREXIT $QIOW_S CHAN=CHAN_DLOMBX,- ; INI WRITE ATTN FUNC=#IO$_SETMODE!IO$M_WRTATTN,- P1=ASTMONITR,- P2=#2 JSB PROC_ERREXIT $GETDVI_S ITMLST=LST_DLOMBXUNT,- ; GET ISUMONMBX UNIT DEVNAM=DSC_ISUDLOMBX JSB PROC_ERREXIT EDIV #-10000000,DELTA_T,DELTA_CONN,WORK ; CVT TIMER INT TO SEC CLRL GBL_COUNT_IAC ; INIT TOTAL IAC PRCS COUNT RSB_INIT: $PUTMSG_S MSGVEC=MSG_STARTUP,- ; ANNOUNCE ISUQUOTA RESTART ACTRTN=MSGACTRTN,- ACTPRM=#3,- FACNAM=DSC_ISUQUOTA RSB .PAGE .SBTTL PROC_ERREXIT ; THIS ROUTINE CHECKS R0 FOR ERROR AND RETURNS IF IT IS OK. OTHERWISE, IT ; LOGS THE ERROR CODE IN R0 AND THE RETURN ADDRESS, DISPLAYS THE MSG TO THE ; OPERATOR, AND THEN EXITS WITH ERROR. PROC_ERREXIT: BLBC R0,10$ ; RETURN IF OK RSB 10$: MOVAL MSG_ERREXIT+4,R6 ; ADR MSGVEC BUFFER MOVL R0,QMSG_FAO_ARG(R6) MOVL (SP),QMSG_FAO_ARG+4(R6) $PUTMSG_S MSGVEC=MSG_ERREXIT,- ; LOG ERROR AN TELL OPER ACTRTN=MSGACTRTN,- ACTPRM=#3 $EXIT_S R0 ; KER-FLUSH!!!!! .PAGE .SBTTL PROC_LOGMPTYQUE ; MASK_LOGMPTYQUE= ^M PROC_LOGMPTYQUE: PUSHR #MASK_LOGMPTYQUE ; SAVE WORK REGS MOVL ARG_EMPTYQUE,MSG_EMPTYQUE+QMSG_FAO_ARG+4 ; FAO ARGS MOVL (SP),MSG_EMPTYQUE+QMSG_FAO_ARG+8 $PUTMSG_S MSGVEC=MSG_EMPTYQUE,- ; GET/LOG MSG ACTRTN=MSGACTRTN,- ACTPRM=#3 RSB_LOGMPTYQUE: POPR #MASK_LOGMPTYQUE ; RLSE WORK REGS RSB .PAGE .SBTTL MSGACTRTN ; THIS ROUTINE SAVES THE MSG CREATED BY $PUTMSG IN STRG_MSGTXT (ASCIC) ; ; CALL MSGACTRTN (MSG, PRM) ; WHERE ; MSG - DESCRIPTOR OF MSG TO RELAY ; PRM - OPTION MASK AND RETURN STATUS FOR THIS ROUTINE ; BIT-0 CONTROLS MSG WRITING (1 WRITE, 0 NO WRITE) ; BIT-1 CONTROLS MSG TO OPERATOR (1 SNDOPR, 0 NO SNDOPR) ARG_COUNT= 0 ARG_MSG= 4 ARG_PRM= 8 .ENTRY MSGACTRTN,^M MOVL ARG_MSG(AP),R11 ; ADR MSG STRG DESCRIPTOR MOVB (R11),STRG_MSGTXT ; SET STRG COUNT MOVC3 (R11),@4(R11),STRG_MSGTXT+1 ; SET STRG TEXT BITL #2,ARG_PRM(AP) ; DISPLAY MSG ON CONSOLE? BEQL RET_MSGACTRTN ; NO MOVL DYN_OPRMSG+4,R6 ; ADR OPER MSG BUFFER MOVZBL STRG_MSGTXT,DYN_OPRMSG ; LEN MSG TEXT MOVC3 DYN_OPRMSG,STRG_MSGTXT+1,- ; INSERT MSG IN OPER MSG BUFFER OPC$L_MS_TEXT(R6) ADDL #OPC$L_MS_TEXT,DYN_OPRMSG ; SET DESCRIPTOR LENGTH $SNDOPR_S MSGBUF=DYN_OPRMSG ; NOTIFY OPER WE HAVE TROUBLE RET_MSGACTRTN: MOVL ARG_PRM(AP),R0 ; SET RETURN STATUS RET .PAGE .SBTTL ASTMONITR ; THIS ROUTINE READS ISUMONMBX AND INTERCEPTS TIMER EXPIRATION. ; ISUMONMBX RECORDS ARE EITHER ACCOUNTING TYPE RECORDS OR MSGS FROM ; ISULOGIN OR ISULOGOUT. THEY ARE IDENTIFIED, AND STORED AT THE END OF ; THE TASK QUEUE. THE WRITE ATTENTION AST FOR ISUMONMBX IS RESET. ; TIMER EXPIRATION IS IDENTIFIED AND STORED AT THE END OF THE TASK ; QUEUE. THE TIMER IS RESET. ; IF THE BUFBLK FREE QUEUE IS EXHAUSTED A DUMMY PASS IS MADE THROUGH ; ASTMONITR TO KEEP THINGS GOING, BUT NO ACTION IS TAKEN ON THE ; RECORD/TIMER DATA. .ENTRY ASTMONITR,^M CLRB FLG_ASTMONITR ; INIT FLAGS REMQUE @FREE_BUFBLK,R11 ; GET MBX BUFFER BVC CASE_ASTMONITR MOVAQ DSC_FREEBFB,ARG_EMPTYQUE ; LOG BUFBLK QUEUE EMPTY JSB PROC_LOGMPTYQUE MOVB #1,FLG_ASTMONITR ; FLAG DUMMY PASS MOVAB DMY_BUFBLK,R11 ; ADR DUMMY BUFBLK CASE_ASTMONITR: MOVL 4(AP),R6 ; CASE SELECTOR MBX OR TIMER CASEB R6,#1,#2$-1$/2-1 1$: .WORD ASTMONMBX-1$ .WORD ASTDLOMBX-1$ .WORD ASTTIMER-1$ 2$: PUSHL R6 ; SAVE SELECTOR MOVAL WORK,R6 ; LOG ERROR MOVL #4,QMSG_LENGTH(R6) MOVL #ISUQUO_BADMSGTYP,QMSG_MSGID(R6) MOVL #2,QMSG_FAO_CNT(R6) MOVAL QMSG_FAO_ARG(R6),R6 CLRL (R6)+ MOVL (SP)+,(R6)+ ELOG_BADOPT: $PUTMSG_S MSGVEC=WORK BRW ASTMON_RLSEBFB ASTMONMBX: $QIOW_S CHAN=CHAN_MONMBX,- ; READ ISUMONMBX FUNC=#IO$_READVBLK,- IOSB=BFB_IOSB(R11),- P1=BFB_BUFR(R11),- P2=#BFB_K_BUFLEN PUSHR #^M ; SAVE STATUS $QIOW_S CHAN=CHAN_MONMBX,- ; RESET WRITE ATTN FUNC=#IO$_SETMODE!IO$M_WRTATTN,- P1=ASTMONITR,- P2=#1 JSB PROC_ERREXIT POPR #^M ; RESTORE STATUS BLBC R0,ASTMBX_LOGERR MOVL BFB_IOSB(R11),R0 BLBC R0,ASTMBX_LOGERR BRW ASTMBX_RECTYPE ASTDLOMBX: $QIOW_S CHAN=CHAN_DLOMBX,- ; READ DEFERRED LOGOUT TMBU FUNC=#IO$_READVBLK,- IOSB=BFB_IOSB(R11),- P1=BFB_BUFR(R11),- P2=#BFB_K_BUFLEN PUSHR R0 ; SAVE STATUS $QIOW_S CHAN=CHAN_DLOMBX,- ; RESET WRTATTN AST FUNC=#IO$_SETMODE!IO$M_WRTATTN,- P1=ASTMONITR,- P2=#2 JSB PROC_ERREXIT POPR R0 ; RESTORE STATUS BLBC R0,ASTMBX_LOGERR MOVL BFB_IOSB(R11),R0 BLBS R0,10$ BRW ASTMBX_LOGERR 10$: MOVAB BFB_BUFR(R11),R10 ; ADR $DELPROC ACCTG RECORD JSB PROC_DLO_MODNAM ; CHANGE USERNAME IN ACCTG REC BRW ASTMBX_RECTYPE ASTMBX_LOGERR: MOVAL WORK,R6 ; LOG ERROR MOVL #5,QMSG_LENGTH(R6) MOVL #ISUQUO_FAILMMBX,QMSG_MSGID(R6) MOVL #3,QMSG_FAO_CNT(R6) MOVAL QMSG_FAO_ARG(R6),(R6)+ CLRL (R6)+ MOVL R0,(R6)+ MOVL BFB_IOSB+4(R11),(R6)+ ELOG_NOMMBX: $PUTMSG_S MSGVEC=WORK BRW ASTMON_RLSEBFB ASTMBX_RECTYPE: MOVAB BFB_BUFR(R11),R10 ; ADR MBX BUFFER TSTW PRCS_TYPE+2(R10) ; ISU MSG OR MSG$_DELPROC BNEQ ASTMBX_ISUMSG ; ISU MSG CMPW ACC$W_MSGTYP(R10),#MSG$_DELPROC ; DLETE PROCESS RECORD? BNEQ ASTMON_BADMSGTYP ; NO MOVW #TSK_K_DELPROC,BFB_TYPE(R11) ; SET TYPE= DELPROC BRW ASTMON_INSTSK ASTMBX_ISUMSG: BITL #PRCS_M_LOGIN,PRCS_STATE(R10) ; ISULOGIN MSG? BEQL 10$ ; NO MOVW #TSK_K_LOGIN,BFB_TYPE(R11) ; TASK_TYPE= LOGIN BRW ASTMON_INSTSK 10$: BITL #PRCS_M_LOGOUT,PRCS_STATE(R10) ; ISULOGOUT MSG? BEQL 20$ ; NO MOVW #TSK_K_LOGOUT,BFB_TYPE(R11) ; TASK_TYPE= LOGOUT BRW ASTMON_INSTSK 20$: BITL #PRCS_M_PRT,PRCS_TYPE(R10) ; PRINT RECORD? BEQL 30$ ; NO REMQUE @FREE_MISCTSK,R7 ; GET MTSK FOR ACCTG BVC 22$ MOVAQ DSC_FREEMTSK,ARG_EMPTYQUE ; LOG FAILURE JSB PROC_LOGMPTYQUE BRW ASTMON_RLSEBFB 22$: MOVW #MTSK_K_ACCTG,MTSK_TYPE(R7) ; INIT MISC TASK MOVW MAX_ACCRETRY,MTSK_TALLY(R7) MOVL #PRCS_M_PRT,MTSK_ACCTYPE(R7) MOVL R11,MTSK_ADR(R7) INSQUE (R7),@QHD_MISCTSK+4 ; QUEUE IT FOR MISCTSK BRW R_R_R_RING 30$: BITL #PRCS_M_ALTER,PRCS_STATE(R10) ; ALTER EXISTING PRCS? BEQL ASTMON_BADMSGTYP ; NO MOVW #TSK_K_ALTER,BFB_TYPE(R11) ; TASK_TYPE= ALTER BRW ASTMON_INSTSK ASTMON_BADMSGTYP: MOVAL WORK,R6 ; LOG ERROR MOVL #8,QMSG_LENGTH(R6) MOVL #ISUQUO_BADMSGTYP,QMSG_MSGID(R6) MOVL #6,QMSG_FAO_CNT(R6) MOVAL QMSG_FAO_ARG(R6),R6 CLRL (R6)+ MOVAL ELOG_BADTYP,(R6)+ MOVL PRCS_TYPE(R10),(R6)+ ; BOTH TYPE AND STATE MOVL BFB_IOSB+4(R11),(R6)+ MOVL #QXR_K_LENUSRNAM,(R6)+ MOVAB PRCS_USERNAME(R10),(R6)+ ELOG_BADTYP: $PUTMSG_S MSGVEC=WORK BRW ASTMON_RLSEBFB ASTTIMER: MOVW #TSK_K_TIMER,BFB_TYPE(R11) ; SET TYPE= TIMER $SETIMR_S DAYTIM=DELTA_T,- ; RESET TIMER ASTADR=ASTMONITR,- REQIDT=#3 BLBS R0,ASTMON_INSTSK MOVL #ISUQUO_BADTIMR,STS_ISUMONITR ; LOG ERROR AND EXIT MOVL R0,STS_ISUMONITR+4 JSB PROC_ERREXIT ASTMON_RLSEBFB: INSQUE (R11),@FREE_BUFBLK+4 ; RELEASE BUFFER BLK JMP RET_ASTMONITR ASTMON_INSTSK: BLBS FLG_ASTMONITR,RET_ASTMONITR ; IF DUMMY PASS THEN NO TASK INSQUE (R11),@QHD_TASK+4 ; PLACE AT END OF TASK QUEUE R_R_R_RING: $WAKE_S ; "SIC'EM SPOT!" RET_ASTMONITR: RET .PAGE .SBTTL PROC_DLO_MODNAM ; MASK_DLO_MODNAM= ^M PROC_DLO_MODNAM: PUSHR #MASK_DLO_MODNAM ; SAVE WORK REGS MOVAQ QHD_MISCTSK,R6 ; LOOP INDEX LOOP_DLO_MODNAM: MOVL (R6),R6 ; NEXT ENTRY CMPL R6,#QHD_MISCTSK ; DONE? BNEQ 10$ ; NO CLRL R0 ; ERROR RETURN BRW RSB_DLO_MODNAM 10$: CMPW MTSK_TYPE(R6),#MTSK_K_DFRLO ; DEFERRED LOGOUT PRCS? BNEQ CONT_DLO_MODNAM ; NO MOVL MTSK_ADR(R6),R7 ; ADR DFRLO PRCS CMPL BFB_IOSB+4(R7),BFB_IOSB+4(R11) ; IS THIS HIM? BEQL DLO_MODNAM ; YES CONT_DLO_MODNAM: BRW LOOP_DLO_MODNAM DLO_MODNAM: MOVAB BFB_BUFR(R7),R7 ; ADR PRCS DATA MOVC3 #QXR_K_LENUSRNAM,PRCS_USERNAME(R7),- ; SET ACCTG RECORD ACC$T_USERNAME(R10) ; USERNAME REMQUE (R6),R6 ; RLSE MISC TASK INSQUE (R6),@FREE_MISCTSK+4 RSB_DLO_MODNAM: POPR #MASK_DLO_MODNAM RSB .PAGE .END ISUMONITR