.TITLE CHG .IDENT /V7.13/ ;******************************************************************* ; ; CHG ; SWITCHES ACCOUNTING (CHARGING) ON OR OFF (PRIVILEGED) OR ; DISPLAYS CURRENT CHARGING RATES (NON-PRIVILEGED). ; THIS TASK IMPLEMENTS THE CHG COMMAND. THE FORMAT OF THIS ; COMMAND (PRIVILEGED OPTIONS) IS ; ; CHG /ON -- SWITCHES CPU ACCOUNTING ON (DEFAULT AT BOOT) ; ; OR ; ; CHG /OFF -- SWITCHES CPU ACCOUNTING OFF. ; ; OR (NON-PRIVILEGED OPTIONS) ; ; CHG DISPLAY CURRENT CHARGING RATES ; ; VERSION: V7 APRIL 81 ; ; STEVE THOMPSON SCHOOL OF CHEMICAL ENGINEERING ; OLIN HALL ; CORNELL UNIVERSITY ; ITHACA NY 14853 ; ; REVISION HISTORY ; ---------------- ; ; SMT732 30-JUL-81 ADDED PAGE CHARGE DISPLAY ; ; SMT753 7-OCT-81 CHANGED NAMES OF CONDITIONAL ASSEMBLY ; PARAMETERS; SEE THE FILES MODIFY.TXT AND ; CONDEF.MAC FOR DETAILS. ; ; SMT769 12-OCT-81 CHANGED TO CENTRALISED BATCH DEVICE NAME ; ; SMT774 24-OCT-81 ADDED SUPPORT FOR MEMORY USAGE CHARGE. ; ; SMT778 31-OCT-81 DON'T REPORT CHARGES IF THE LOGGING TASK IS ; NOT ACTIVE. ; ; SMT788 13-NOV-81 ALLOW CHARGE DISPLAY IF GMCR$ ERROR ; ; SMT798 9-JAN-82 ALLOW SWITCH TO FOLLOW COMMAND NAME WITHOUT ; AN INTERVENING SPACE. ; ; 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 "$GNBLK" BY "GT.NXT" ; REPLACED "$FMTDV" BY "FM.DEV" ; ;******************************************************************* .MCALL GMCR$,EXIT$S,DIR$,QIOW$ .MCALL EXST$ ACCDF$ ; DEFINE ACCOUNTING OFFSETS BITDF$ ; DEFINE ACCOUNTING BITS BATDV$ ; DEFINE BATCH STREAM DEVICE NAME CR=15 ; CARRIAGE RETURN LF=12 ; LINEFEED HT=11 ; HORIZONTAL TAB LUN=1 ; TI: I/O LUN EFN=1 ; EVENT FLAG FOR I/O ; ; MACROS ; .MACRO PRINT ERR MOV ERR,DPBOUT+Q.IOPL MOV ERR'SZ,DPBOUT+Q.IOPL+2 DIR$ #DPBOUT .ENDM .PAGE .SBTTL ERROR MESSAGES ; ; ERROR MESSAGES ; .NLIST BEX .IIF DF AA$V40, .ENABL LC ERR1: .ASCII /CHG -- Syntax error/ ERR1SZ=.-ERR1 ERR2: .ASCII /CHG -- Bad switch/ ERR2SZ=.-ERR2 ERR3: .ASCII /CHG -- Privileged command/ ERR3SZ=.-ERR3 ERR4: .ASCII /CHG -- Logging task not installed/ ERR4SZ=.-ERR4 ERR5: .ASCII /CHG -- Logging task not active/ ERR5SZ=.-ERR5 ERR6: .ASCII /CHG -- Memory allocation failure/ ERR6SZ=.-ERR6 ERR7: .ASCII /CHG -- Accounting is not active/ ERR7SZ=.-ERR7 .EVEN .PAGE .SBTTL TEXT MESSAGES ; ; TEXT MESSAGES ; .ENABL LC USRMSG: .ASCIZ /Current charging rates for user [/ USRMS1: .ASCIZ /] at / CPUMSG: .ASCIZ /Central Processor Time (per hour): / .IF DF AA$QIO & AA$TCQ QIOMSG: .ASCIZ %I/O Operations (per million): % .IFTF CONMSG: .ASCIZ /Connect Time (per hour): / DSKMSG: .ASCIZ /Disk (per Megabyte per week): / PAGMSG: .ASCIZ /Printing (per page):/ .IF DF AA$MEM MEMMSG: .ASCIZ /Memory usage (per KW-hour): / .ENDC ; DF AA$MEM .PAGE .SBTTL LOCAL DATA STORAGE .EVEN FLAG: .WORD 0 ; ACCOUNTING ON/OFF FLAG ; 0=ON 1=OFF LOGNAM: .RAD50 /LOG.../ LOGPTR: .WORD 0 GMCR: GMCR$ BUF=GMCR+2 DPBOUT: QIOW$ IO.WVB,LUN,EFN,,,, ; OUTPUT DPB EXST: EXST$ EX$SUC CPUCHG: .WORD 0 ; CPU TICKS PER HOUR .WORD K$$TPS ; CPUBLK: .WORD $CPU1 ; CPU CHARGE CONSTANTS .WORD $CPU2 ; .IFT ; DF AA$QIO & AA$TCQ QIOCHG: .WORD 17 ; 1,000,000 I/O REQUESTS .WORD 41100 ; QIOBLK: .WORD $QIO1 ; I/O CHARGE CONSTANTS .WORD $QIO2 ; .IFTF CONCHG: .WORD 0 ; CONNECT TICKS PER HOUR (COPIED FROM .WORD 0 ; CPUCHG) CONBLK: .WORD $CON1 ; CONNECT CHARGE CONSTANTS .WORD $CON2 ; DSKCHG: .WORD 463 ; 2000. BLOCKS FOR 1 WEEK .WORD 117000 ; (7*60.*24.*2000.) DSKBLK: .WORD $DSK1 ; DISK CHARGE CONSTANTS .WORD $DSK2 ; PAGCHG: .WORD 0 ; ONE PAGE PRINTED .WORD 1 ; PAGBLK: .WORD $PAG1 ; PAGE CHARGE CONSTANTS .WORD 1 ; .IF DF AA$MEM MEMCHG: .WORD 0 ; 1 KW-HOUR (1024.*3600./64. 64W-SECS) .WORD 57600. ; MEMBLK: .WORD $MEM1 ; MEMORY CHARGE CONSTANTS .WORD $MEM2 ; .ENDC ; DF AA$MEM SPCBLK: .WORD 0 ; ARG. BLK. FOR RATE ADJUSTMENT .WORD 0 ; NTERM: .WORD 0 ; BINARY TERMINAL NUMBER LUIC: .WORD 0 ; LOGON UIC .PSECT NSCONN NSCTAB::.WORD 0 ; SPECIAL CONNECT RATE TABLE. ; FILLED IN BY TKB .PSECT NSCPU NCPTAB::.WORD 0 ; SPECIAL CPU RATE TABLE ; FILLED IN BY TKB .PSECT .PAGE .SBTTL ROUTINE CODE $CHGEP: ; ; DECODE THE COMMAND LINE AND CHECK SYNTAX ; DIR$ #GMCR ; GET THE COMMAND LINE BCS 17$ ; IF CS NONE, JUST DISPLAY RATES MOV #BUF,R0 ; GET BUFFER ADDRESS 15$: CALL GT.NXT ; GET NEXT NON-BLANK CHARACTER BCC 25$ ; OK 17$: CALL RATES ; NO COMMAND PARAMETER, JUST DISPLAY RATES EXIT$S ; AND EXIT 20$: PRINT #ERR1 ; ERROR, NULL COMMAND LINE MOV #EX$ERR,EXST+E.XSTS ; SET ERROR STATUS 5$: JMP EXIT ; EXIT 25$: CMPB R2,#'/ ; SWITCH COMING BEFORE A SPACE? BEQ 26$ ; IF EQ YES TST R1 ; ANY BLANKS SEEN? BEQ 15$ ; IF EQ NO, CONTINUE SCAN CMPB R2,#'/ ; SWITCH COMING? BNE 20$ ; IF NE NO 26$: CALL GT.NXT ; GET FIRST CHARACTER OF SWITCH BCS 30$ ; EOL IS BAD SWITCH CMPB R2,#'O ; LETTER O? BEQ 35$ ; IF EQ YES 30$: PRINT #ERR2 ; NO, ILLEGAL PARAMETER BR 5$ ; EXIT 31$: CALL GT.NXT ; GET NEXT NON-BLANK CHARACTER BCS 30$ ; END OF LINE IS ERROR BR 40$ ; CONTINUE 32$: CALL GT.NXT ; GET NEXT NON-BLANK CHARACTER BCS 30$ ; END OF LINE IS ERROR 35$: CALL GT.NXT ; GET NEXT NON-BLANK CHARACTER BCS 30$ ; EOL IS ERROR CMPB R2,#'N ; IS THIS THE 'ON' PARAMETER? BEQ 40$ ; IF EQ YES CMPB R2,#'F ; IS THIS THE 'OFF' PARAMETER? BNE 30$ ; ONLY 'F' IS LEGAL CALL GT.NXT ; LOOK FOR SECOND "F" BCS 30$ ; ILLEGAL IF NOTHING THERE CMPB R2,#'F ; GOT ONE, IS IT F? BNE 30$ ; ONLY F IS LEGAL MOV #AC.SET,FLAG ; SET FLAG FOR "OFF" 40$: CALL GT.NXT ; CHECK FOR END OF SWITCH BCC 30$ ; ONLY CARRY SET IS GOOD ; ; CHECK PRIVILEGE STATUS - ONLY PRIVILEGED USERS CAN USE ...CHG ; WITH THE /ON AND /OFF SWITCHES ; MOV $TKTCB,R1 ; GET OUR TCB ADDRESS MOV T.UCB(R1),R1 ; GET TI: UCB ADDRESS BIT #U2.PRV,U.CW2(R1) ; ARE WE PRIVILEGED BNE 42$ ; IF NE YES, OK TO PROCEED PRINT #ERR3 ; PRIVILEGE VIOLATION MOV #EX$ERR,EXST+E.XSTS ; SET ERROR STATUS BR 5$ ; AND EXIT ; ; 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 #ERR4 ; ERROR, IT WASN'T THERE MOV #EX$SEV,EXST+E.XSTS ; SET SEVERE EXIT STATUS BR EXIT ; THAT'S IT 45$: BIT #TS.EXE,T.STAT(R0) ; IS THE LOGGING TASK ACTIVE? BEQ 50$ ; IF EQ YES PRINT #ERR5 ; NO, ERROR MOV #EX$SEV,EXST+E.XSTS ; SET SEVERE EXIT STATUS BR EXIT ; DON'T SEND REQUEST 50$: MOV R0,LOGPTR ; SAVE LOG...'S TCB ADDRESS ; ; SEND REQUEST TO ACCOUNTING SYSTEM ; CALL $SWSTK,60$ ; SWITCH TO SYSTEM STACK MOV #B.LCPU,R1 ;; GET LENGTH OF BUFFER TO ALLOCATE ;; *NOTE* THE CHG COMMAND SHARES PACKET ;; *NOTE* DEFINITIONS WITH THE CPU ;; *NOTE* COMMAND CALL $ALOCB ;; ALLOCATE IT BCS 55$ ;; ERROR MOV #,B.MASK(R0) ;; SET COMMAND IN PACKET MOV FLAG,B.FLAG(R0) ;; SET REPORTING FLAG MOV R0,R1 ;; COPY BLOCK ADDRESS TO R1 MOV LOGPTR,R0 ;; GET LOG...'S TCB ADDRESS CALLR $EXRQF ;; QUEUE PACKET AND START LOG... 55$: CLR LOGPTR ;; SET FLAG FOR ALLOCATION FAILURE RETURN ;; BACK TO TASK LEVEL 60$: TST LOGPTR ; WAS THERE AN ERROR? BNE EXIT ; IF NE NO, EXIT PRINT #ERR6 ; YES, SAY SO MOV #EX$SEV,EXST+E.XSTS ; SET SEVERE EXIT STATUS BR EXIT ; EXIT EXIT: DIR$ #EXST ; EXIT WITH CORRECT STATUS EXIT$S ; JUST IN CASE .PAGE .SBTTL ROUTINE TO DISPLAY CHARGING RATES ;+ ; *** RATES DISPLAYS CHARGING RATES CURRENTLY IN EFFECT ; FOR THE CURRENT DEFAULT USER. WE VERIFY THAT THE ; LOGGING TASK IS RUNNING. ; ;- RATES: MOV #LOGNAM,R3 ; GET NAME OF LOGGING TASK CALL $SRSTD ; LOOK FOR IT IN THE STD BCC 1$ ; OK 101$: PRINT #ERR7 ; ERROR, IT WASN'T THERE RETURN ; 1$: BIT #TS.EXE,T.STAT(R0) ; IS THE LOGGING TASK ACTIVE? BNE 101$ ; IF NE NO MOV #BUF,R0 ; GET OUTPUT BUFFER ADDRESS MOVSTR #USRMSG ; START OFF NAME OF USER MESSAGE MOV $TKTCB,R5 ; GET OUR TCB ADDRESS MOV T.UCB(R5),R5 ; THEN TI: UCB ADDRESS CLR R1 ; GET GROUP NUMBER BISB U.LUIC+1(R5),R1 ; CALL OC.TAL ; FORMAT GROUP NUMBER MOVB #',,(R0)+ ; INSERT A COMMA CLR R1 ; GET MEMBER NUMBER BISB U.LUIC(R5),R1 ; CALL OC.TAL ; FORMAT MEMBER NUMBER MOVSTR #USRMS1 ; INSERT DEVICE NAME MESSAGE MOV R5,R3 ; COPY UCB ADDRESS TO R3 CALL FM.DEV ; FORMAT DEVICE NAME SUB #BUF,R0 ; CALCULATE LENGTH OF STRING MOV R0,DPBOUT+Q.IOPL+2 ; INSERT IT IN THE DPB DIR$ #DPBOUT ; PRINT THE MESSAGE MOV U.DCB(R5),R2 ; POINT TO OUR DCB MOV U.LUIC(R5),LUIC ; SAVE CURRENT LOGON UIC MOV R5,R0 ; COPY UCB ADDRESS SUB D.UCB(R2),R0 ; COMPUTE RELATIVE UCB ADDRESS MOV D.UCBL(R2),R1 ; GET UCB LENGTH CALL $DIV ; COMPUTE RELATIVE UNIT NUMBER ADD D.UNIT(R2),R0 ; COMPUTE ABSOLUTE UNIT NUMBER BIC #177400,R0 ; ZAP ANY RUBBISH IN THE HIGH BYTE MOV R0,NTERM ; AND SAVE THE ANSWER .IF DF AA$BAT MOV R2,-(SP) ; SAVE DCB ADDRESS ON STACK .IFTF MOV CPUCHG,R2 ; GET HIGH ORDER TICKS MOV CPUCHG+2,R3 ; GET LOW ORDER TICKS MOV #3600.,R0 ; SET SECONDS PER HOUR CALL $DMUL ; CONVERT TO TICKS MOV R1,CPUCHG+2 ; SAVE THE RESULT MOV R0,CPUCHG ; .IFT MOV (SP)+,R2 ; RESTORE DCB ADDRESS CMP D.NAM(R2),BATDEV ; ARE WE ON A VIRTUAL TERMINAL? BEQ 5$ ; IF EQ YES, CONNECT RATE IS ALWAYS ZERO .ENDC ; DF AA$BAT MOV R1,CONCHG+2 ; AND COPY IT TO CONNECT TIME BUFFER MOV R0,CONCHG ; MOV #NSCTAB,R0 ; GET ADDRESS OF NON-STANDARD CONNECT RATE TABLE MOV #CONCHG,R5 ; GET ADDRESS OF CONNECT TIME BUFFER CALL ADJUST ; ADJUST THIS TIME FOR ANY UNUSUAL CONNECT RATE 5$: MOV #NCPTAB,R0 ; GET ADDRESS OF NON-STANDARD CPU RATE TABLE MOV #CPUCHG,R5 ; GET ADDRESS OF CPU TIME BUFFER CALL ADJUST ; ADJUST THIS TIME FOR ANY UNUSUAL CPU RATE .IFT MOV #NCPTAB,R0 ; NON-STANDARD CPU RATE APPLIES FOR I/O AS WELL MOV #QIOCHG,R5 ; CALL ADJUST ; .IFTF MOV #CPUCHG,R5 ; SET UP CPU TIME ADDRESS FOR ML.DV MOV #CPUMSG,R1 ; GET CPU TEXT MESSAGE ADDRESS MOV #CPUBLK,R4 ; AND ML.DV ARGUMENT BLOCK ADDRESS CALL 10$ ; CALCULATE AND DISPLAY CHARGE .IFT MOV #QIOCHG,R5 ; REPEAT FOR I/O CHARGE MOV #QIOBLK,R4 ; MOV #QIOMSG,R1 ; CALL 10$ ; .ENDC ; DF AA$QIO & AA$TCQ MOV #CONCHG,R5 ; REPEAT FOR CONNECT CHARGE MOV #CONBLK,R4 ; MOV #CONMSG,R1 ; CALL 10$ ; MOV #DSKCHG,R5 ; REPEAT FOR DISK CHARGE MOV #DSKBLK,R4 ; MOV #DSKMSG,R1 ; CALL 10$ ; MOV #PAGCHG,R5 ; REPEAT FOR PAGE CHARGE MOV #PAGBLK,R4 ; MOV #PAGMSG,R1 ; .IF DF AA$MEM CALL 10$ ; MOV #MEMCHG,R5 ; REPEAT FOR MEMORY USAGE MOV #MEMBLK,R4 ; MOV #MEMMSG,R1 ; FALL THROUGH TO 10$ .ENDC ; DF AA$MEM 10$: MOV R1,-(SP) ; SAVE TEXT MESSAGE ADDRESS CALL ML.DV ; CALCULATE THE CHARGE MOV R2,-(R5) ; SAVE IT IN ORIGINAL BUFFER MOV R1,-(R5) ; MOV #BUF,R0 ; GET OUTPUT BUFFER ADDRESS MOV (SP)+,R1 ; RESTORE TEXT MESSAGE ADDRESS CALL MV.STR ; PUT TEXT IN OUTPUT BUFFER MOV R5,R1 ; POINT R1 TO CHARGE CALL FM.CHG ; AND FORMAT THE CHARGE SUB #BUF,R0 ; CALCULATE MESSAGE LENGTH MOV R0,DPBOUT+Q.IOPL+2 ; SET BUFFER LENGTH IN DPB DIR$ #DPBOUT ; WRITE OUT THE MESSAGE RETURN ; AND RETURN TO CALLER ;+ ; *** ADJUST - DETERMINE IF SPECIAL RATE APPLIES AND MODIFY ; THE BASIC TIME BUFFER ACCORDINGLY. ; ; THIS ROUTINE SCANS A NON-STANDARD RATE TABLE TO SEE ; IF THERE IS AN ENTRY THAT APPLIES IN THE PRESENT CASE. THE ; TABLE FORMAT IS DESCRIBED IN THE DOCUMENTATION. ; ; INPUT: ; R0 ADDRESS OF NON-STANDARD RATE TABLE ; R5 ADDRESS OF TIME BUFFER FOR MODIFICATION ; NTERM BINARY PHYSICAL TERMINAL NUMBER ; LUIC LOGON UIC (MAY NOT BE ORIGINAL FOR PRIVILEGED ; USERS IF THEY HAVE SET /UIC) ; ;- ADJUST: ; 10$: MOV (R0)+,R1 ; GET NEXT TERMINAL NUMBER BEQ 30$ ; IF EQ, END OF TABLE BLT 15$ ; IF LT ALL TERMINALS MATCH CMP R1,NTERM ; SAME TERMINAL AS OURS? BEQ 15$ ; IF EQ YES CMP (R0)+,(R0)+ ; POINT TO NEXT ENTRY BR 10$ ; AND LOOP 15$: MOV (R0)+,R1 ; GET USER DESCRIPTOR WORD BEQ 25$ ; IF EQ IT APPLIES TO EVERYONE TSTB R1 ; IS TABULATED MEMBER CODE ZERO? BEQ 20$ ; IF EQ YES, GROUP APPLIES ONLY CMP LUIC,R1 ; DOES FULL UIC MATCH? BEQ 25$ ; IF EQ YES 16$: TST (R0)+ ; POINT TO NEXT ENTRY BR 10$ ; AND LOOP 20$: SWAB R1 ; POSITION GROUP CODE IN LOW BYTE CMPB LUIC+1,R1 ; DOES GROUP CODE MATCH? BNE 16$ ; IF NE NO, GO TO NEXT ENTRY 25$: MOV (R0)+,R1 ; GET CHARGE ALTERATION FACTOR BEQ 35$ ; IF EQ THERE IS NO CHARGE MOV #SPCBLK+2,R4 ; GET ADDRESS OF ARGUMENTS BLOCK MOV R1,(R4) ; SET ML.DV DIVISOR BIC #177400,(R4) ; CLEAR HIGH ORDER BITS SWAB R1 ; POSITION FOR MULTIPLICAND MOV R1,-(R4) ; SET UP MULTIPLICAND BIC #177400,(R4) ; CALL ML.DV ; READJUST THE CONNECT TIME MOV R2,-(R5) ; SAVE THE RESULT MOV R1,-(R5) ; 30$: RETURN ; RETURN TO CALLER 35$: CLR (R5) ; RATE IS ZERO FOR THIS USER CLR 2(R5) ; RETURN ; RETURN TO CALLER .END $CHGEP