10 !MONEY VERSION 6B EDIT 0 11-OCT-76 ! !NEW VERSION OF MONEY TO UTILIZE $ACCT.VIR AS CREATED !AND MAINTAINED BY NEW REACT PROGRAM. 11 !4-Mar-77 PEEK changed to 6B format. !29-Aug-77 Comments added for submission to DECUS. 20 !INSTRUCTIONS: !Program operates differently for ordinary user, group leader, or !priveleged user. Operation for the ordinary user & group leader !is described in the file MONEY.DOC. For the priveleged user, !there are added options for resetting the accounting data; !only accounts in $ACCT.VIR are dumped, therefore, it is essential !that $ACCT.VIR accurately reflects the accounts on the disk !(if in doubt use the BUILD option of REACT before using this !program). ! !The priveleged user may dump selectively by ppn, or by wildcard !on either proj# or prog# (e.g., 3,* dumps all ppn's with project# 3, !*,0 dumps all project leader accounts.) If an output device !other than KB: is selected, the user may append "/DET" to the !filespec and MONEY will run detached (it simply hibernates when !done-no broadcast back to KB0: is currently implemented). !The RESET option will work only with a full dump; the date of last !reset is stored in $ACCT.VIR and is used whenever MONEY is run. !Devices other than SY: may be specified, but only accounts from !$ACCT.VIR will be scanned. ! !Output is always in order by ppn; group and grand totals are !also printed. Program is setup to run at 8 lines/inch on !standard 8 1/2 by 11 inch paper. For different forms length, !modify L0% and L1% in line 1030; L1% is max number of lines !per page, with no new group beginning beyond line L0% on a page. ! !Program should be saved with a protection code of <232>; great !care has been taken to insure that non-priveleged users cannot !do anything dangerous (security-wise) with this program. 900 DIM M%(30%), M1%(30%), S(7%), T0(7%), T1(7%), A%(1023%) ! 910 DIM#2%, A0%(1023%,4%) ! !$ACCT.VIR FILE AS CREATED AND MAINTAINED BY REACT. !OF INTEREST HERE ARE: !(0,0) # OF ACCOUNTS ON THE SYSTEM !(0,1) DATE OF LAST RESET/ !(N,0) P,PN OF ACCOUNTS (ASCENDING ORDER.) 1000 ON ERROR GOTO 19000 \M$=SYS(CHR$(6%)+CHR$(-7%)) \Q3$=CHR$(13%)+CHR$(10%) \PRINT 'MONEY V6B-00';Q3$ !SET CTRL/C TRAP AND IDENTIFY OURSELF. 1010 P%=PEEK(PEEK(PEEK(520%)+8%)+24%) \P1%,Q1%=255% AND SWAP%(P%) \P0%,Q0%=255% AND P% \R9%,S9%,P9%,D9%,L%=0% !USER'S P,PN IS Q1%,Q0%; R9=RESET FLAG; S9=SELECT FLAG; !P9=PRINT PASSWORD FLAG; L = LINE COUNT. 1020 M%(J%)=0% FOR J%=2% TO 30% \U0$="####.## ####.## ####.## ##### ##### ## #####.# ##.#" \U1$="####.## ####.## ####.## ##### ##### #####.# ##.#" !INIT USING STRINGS AND SYS() ARRAY. 1030 OPEN '$ACCT.VIR' FOR INPUT AS FILE 2% \N0%=A0%(0%,0%) \D0%=A0%(0%,1%) \L0%=65% \L1%=L0%+10% !GET DATE OF LAST RESET (D0%) AND INIT LINE COUNT FOR 8/INCH. 1040 IF P1%=1% THEN 2000 ELSE IF P0%=0% THEN INPUT 'SELF OR GROUP ( = SELF)';A$ \GOTO 2000 IF LEFT(CVT$$(A$,255%),1%)='G' !ONLY SPECIAL PEOPLE GO BEYOND 1100. 1100 ! ! S T A N D A R D N O N - P R I V E L E G E D ! 1110 OPEN 'KB:' FOR OUTPUT AS FILE 1% \M%(0%)=30% \M%(1%)=6% \M%(2%)=14% \GOSUB 4000 \GOTO 8000 !DO LOOKUP ON USER'S NUMBER AND THEN EXIT. 2000 ! ! P R I V E L E G E D O R G R O U P L E A D E R ! 2010 PRINT 'OUTPUT TO ( = KB:)'; \INPUT LINE A$ \ A$=CVT$$(A$,255%) \IF P1%=1% THEN D9%=INSTR(1%,A$,'/DET') \IF D9% THEN A$=LEFT(A$,D9%-1%) \D9%=-1% !/DET SWITCH OK FOR PRIVELEGED USER. 2020 A$='KB:' UNLESS LEN(A$) \OPEN A$ FOR OUTPUT AS FILE 1% \INPUT 'SELECTIVE ( = NO)';A$ \S9%=(ASCII(CVT$$(A$,255%))=89%) !OPEN OUTPUT FILE; S9%=-1 IF SELECTIVE, =0 IF NOT. 2030 A%(J%)=A0%(J%,0%) FOR J%=1% TO N0% !INITIALIZE PPN ARRAY FROM $ACCT.VIR; 2040 IF P1%=1% THEN INPUT'PASSWORDS (=NO)';A$ \P9%=ASCII(CVT$$(A$,255%))=89% \INPUT'RESET (=NO)';A$ \R9%=ASCII(CVT$$(A$,255%))=89% \INPUT'DEVICE (=SY0:)';A$ \CHANGE SYS(CHR$(6%)+CHR$(-10%)+A$) TO M% ! 2050 M%(0%)=30% \M%(1%)=6% \M%(2%)=14% \M%(J%)=0% FOR J%=3% TO 22% \M%(27%),M%(28%),M%(29%),M%(30%)=0% !INIT M% FOR ACCOUT DUMP SYS() CALL. 23-26 ARE DEVICE. 2055 IF D9% THEN PRINT 'DETACHING...';Q3$;Q3$;Q3$ \M$=SYS(CHR$(6%)+CHR$(7%)) !DETACH IF '/DET' SWITCH WAS SPECIFIED. 2060 IF S9% THEN IF P1%=1% THEN 2100 ELSE 2200 ELSE IF P1%=1% THEN 2300 ELSE 2400 !GOTO SEL-PRIV, SEL-GROUP, ALL-PRIV, ALL-GROUP, RESP. 2100 ! ! S E L E C T I V E - P R I V E L E G E D ! 2110 INPUT '[P,PN]';P1$,P0$ \T0(J%)=0. FOR J%=0% TO 7% \P1%=VAL(P1$) !INIT GROUP TOTALS; ERR=52 TRAP IF P1$='*'. 2120 P0%=VAL(P0$) !SAME TRAP IF P0$='*'. 2130 IF P1%=255% AND P0%=255% THEN S9%=0% \GOTO 2300 !*,* IS REALLY THE SAME AS NON-SELECTIVE. 2140 IF P1%<255% AND P0%<255% THEN GOSUB 4000 \GOTO 2110 !PRINT THE STUFF FOR THE REQUESTED P,PN (NEITHER IS WILD HERE), AND !GET NEXT ONE. 2150 N%=0% \GOSUB 7100 IF L%=0% \GOSUB 5000 !PRINT HEADER (IF HAVEN'T DONE SO ALREADY) AND GET FIRST !MATCHING NUMBER (EXACTLY ONE OF P0% OR P1% IS 'WILD' HERE. 2160 WHILE M%(7%)>=0% \GOSUB 6000 \GOTO 2170 IF M1%(0%)<0% \GOSUB 7000 \GOSUB 7200 \GOSUB 5000 !DO THE SYS() CALL; CONVERT TO OUTPUT FORMAT; PRINT IT; !GET NEXT ONE. CONTINUE TILL NO MATCH (M%(7)=-1). 2170 NEXT \IF T0(7%)=0. THEN PRINT Q3$;'NO ACCOUNTS MATCHING [';P1$;',';P0$;']' ELSE GOSUB 7300 !T0(7) COUNTS NUMBER OF MATCHES IN GROUP; PRINT GROUP TOTAL ONLY IF >1. 2180 GOTO 2100 !END OF SELECTIVE-PRIVELEGED SECTION. 2200 ! ! S E L E C T I V E - G R O U P L E A D E R ! 2210 INPUT 'PROGRAMMER NUMBER'; P0$ \P0%=VAL(P0$) !GROUP LEADERS CAN ONLY LOOK AT THEIR OWN GROUP. 2220 GOSUB 4000 \GOTO 2210 !GIVE INFO ON THE NUMBER; ERR=52 RESUMES AT 'ALL-GROUP'. 2300 ! ! F U L L D U M P - P R I V E L E G E D ! 2310 M1%,P1%=255% AND SWAP%(A%(1%)) \P0%=255% AND A%(1%) \IF R9% THEN A0%(0%,1%)=PEEK(512%) \M%(5%),M%(6%)=255% !INIT FOR FULL DUMP; M1% IS LAST PROJECT # READ; NOTE ONLY !FOR THIS OPTION WILL 'RESET' ACTUALLY TAKE EFFECT. 2320 FOR N%=2% TO N0% \GOSUB 4000 \P1%=255% AND SWAP%(A%(N%)) \P0%=255% AND A%(N%) \GOTO 2340 IF P1%=M1% !AFTER DUMPING CURRENT P,PN AND GETTING NEXT ONE, SKIP SUBTOTALS !UNLESS PROJECT # CHANGES. 2330 M1%=P1% \GOSUB 7300 \IF L%>=L0% THEN PRINT#1%, CHR$(12%); \GOSUB 7100 !ACCUMULATE AND PRINT TOTALS; FF IF AT ENDPAGE. 2340 NEXT N% \GOSUB 4000 \GOSUB 7300 !DO THE LAST ONE AND ITS GROUP TOTAL. 2350 PRINT#1%,Q3$;'GRAND TOTAL';Q3$;T1(7%);'USERS';TAB(10%-P9%*10%); \PRINT#1%, USING U1$, T1(0%),T1(1%),T1(2%),T1(3%),T1(4%),T1(6%), T1(6%)/((T1(0%)+1.E-5)*.6) !PRINT OUT THE GRAND TOTAL 2360 GOTO 8000 !NOTHING ELSE TO DO HERE SO QUIT. 2400 ! ! E N T I R E G R O U P F O R L E A D E R ! 2410 GOSUB 7100 \N%=0% \P0%=255% \GOSUB 5000 !PRINT HEADER AND FIND LEADER'S P,PN; SET P0% TO ALL FLAG AND !LOOKUP FIRST NUMBER (LEADER'S). 2420 WHILE M%(7%)>=0% \GOSUB 6000 \GOTO 2430 IF M1%(0%)<0% \GOSUB 7000 \GOSUB 7200 \GOSUB 5000 !DO LOOKUP, CONVERT IT, PRINT IT, AND GET NEXT NUMBER. 2430 NEXT \GOSUB 7300 \GOTO 8000 !PRINT GROUP TOTALS AND EXIT. 4000 ! ! S T A N D A R D C A L L I N G S E Q U E N C E ! 4010 M%(7%)=P0% \M%(8%)=P1% \GOSUB 7100 IF L%=0% \GOSUB 6000 \RETURN IF M1%(0%)<0% \GOSUB 7000 \GOSUB 7200 \RETURN !GET AND PRINT INFO FOR [P1,P0] 5000 ! ! P , P N S C A N O F A % ( ) A R R A Y ! 5010 A1%=SWAP%(P1%) \A%=A1%+P0% \A%(N0%+1%)=A% \N%=N%+1% \IF P0%=255% THEN N%=N%+1% UNTIL (A%(N%) AND -256%)=A1% ELSE N%=N%+1% UNTIL (A%(N%) AND 255%)=P0% !GET NEXT MATCHING P,PN 5020 IF N%>N0% THEN M%(7%),M%(8%)=-1% ELSE M%(7%)=A%(N%)AND255% \M%(8%)=SWAP%(A%(N%))AND 255% !RETURN FLAG IF SCAN UNSUCCESSFUL, ELSE P,PN IN M%() FOR SYS() CALL. 5030 RETURN !END OF SCAN FOR P,PN. NOTE ASSUME THAT EXACTLY ONE OF P0% OR P1% !IS 255. 6000 ! ! A C C O U N T D U M P S Y S ( ) C A L L ! 6010 CHANGE M% TO M$ \CHANGE SYS(M$) TO M1% !ACCOUNT DUMP SYS CALL; ANY ERRORS TRAP AND RESUME AT NEXT LINE 6020 RETURN !NOT MUCH TO IT. 7000 ! ! C O N V E R T M 1 % ( ) F O R O U T P U T ! 7010 S(1%)=(256.*M1%(16%)+M1%(15%))/60. \S(2%)=(256.*M1%(20%)+M1%(19%))/60. \S(3%)=256.*M1%(6%)+M1%(5%) \S(4%)=256.*M1%(28%)+M1%(27%) \S(5%)=M1%(29%) !GET CONNECT(HRS), DEVICE(HRS), BLOCKS IN USE, QUOTA, AND UFD CLUSTER. 7020 S(0%)=256.*M1%(14%)+M1%(13%) \S(6%)=256.*M1%(18%)+M1%(17%) \S%=M1%(21%)+SWAP%(M1%(22%)) !GET LOWORDER PART OF CPU AND KCT'S; S% HIGH ORDER PART OF SAME. 7030 S(0%)=S(0%)+65536.*(S%/1024%) \S(6%)=S(6%)+65536.*(S% AND 1023%) \IF S(0%)=0. THEN S(7%)=0. ELSE S(7%)=S(6%)/S(0%) !NOW HAVE CPU IN .1 SECS AND KCTS; AVERAGE K IS QUOTIENT OF THEM. 7040 S(0%)=S(0%)/600. \S(6%)=S(6%)/1000. \T0(J%)=T0(J%)+S(J%) FOR J%=0% TO 6% \T0(7%)=T0(7%)+1. \RETURN !CONVERT CPU TO MIN., KCTS TO 1000'S; UPDATE GROUP COUNTER 7100 ! ! P R I N T H E A D E R S ! 7110 L%=0% \GOTO 7130 IF Q1%<>1% \L2%=2% \PRINT#1%,Q3$;'ACCOUNTING DUMP OF '; \IF M%(23%)=0% THEN PRINT#1%, 'SY0'; ELSE PRINT#1%, CHR$(M%(23%));CHR$(M%(24%)); \PRINT#1%, CHR$(48%+M%(25%)); IF M%(26%) 7120 PRINT#1%, ': ON ';DATE$(0%);' AT ';TIME$(0%); \PRINT#1%, ' ***DATA BEING RESET***'; IF R9% !SPECIAL HEADER FOR PRIVELEGED USER; MAKE CLEAR DATA IS BEING RESET. 7130 PRINT#1%, Q3$;'USAGE SINCE: ';DATE$(D0%);Q3$;' [P,PN] '; \PRINT#1%, ' PASSWORD '; IF P9% !PRINT COMMON PART OF HEADER, INCLUDING DATE OF LAST RESET. 7140 PRINT#1%, ' CPU CONNECT DEVICE DISK QUOTA UFD KCTS'; ' AVE.';Q3$;TAB(10%-P9%*10%); ' (MIN) (HOURS) (HOURS) (BLOCKS) (/1000) SIZE';Q3$ \L%=L%+4% \RETURN !FINAL HEADER AND RETURN. 7200 ! ! P R I N T A L I N E ! 7210 PRINT#1%, FNP$(M1%(8%),M1%(7%));TAB(10%); \PRINT#1%, ' ';RAD$(M1%(9%)+SWAP%(M1%(10%))); RAD$(M1%(11%)+SWAP%(M1%(12%)));TAB(20%); IF P9% !P,PN AND PASSWORD (IF SELECTED) 7220 PRINT#1%, USING U0$, S(0%),S(1%),S(2%),S(3%),S(4%),S(5%),S(6%),S(7%) \L%=L%+1% \IF L%>L1% THEN PRINT#1%, CHR$(12%); \L%=0% \GOSUB 7100 !PRINT THE STUFF; SKIP PAGE IF ENDPAGE. 7230 RETURN !AND THAT'S IT. 7300 ! ! P R I N T G R O U P T O T A L S ! 7310 T1(J%)=T1(J%)+T0(J%) FOR J%=0% TO 7% \IF T0(7%)<=1. THEN PRINT#1% \L%=L%+1% \GOTO 7330 !NO SUBTOTALS IF ONLY ONE NUMBER IN GROUP. 7320 PRINT#1%,STRING$(70%,45%);Q3$;'FOR GROUP';TAB(10%-P9%*10%); \PRINT#1%, USING U1$, T0(0%),T0(1%),T0(2%),T0(3%),T0(4%),T0(6%), T0(6%)/((T0(0%)+1.E-5)*.6) \PRINT#1% \L%=L%+3% !SUBTOTALS PRINTED. 7330 T0(J%)=0. FOR J%=0% TO 7% \RETURN !ZERO THE GROUP TOTALS BEFORE RETURNING. 8000 ! ! G E N E R A L E X I T ! 8010 CLOSE 1%,2% \PRINT IF POS(0%) \M$=SYS(CHR$(9%)) !EXIT TO MONITOR - STANDARD EXIT FROM PROGRAM.. 10000 ! ! F U N C T I O N S ! 10100 DEF FNE$(E%)=CVT$$(RIGHT(SYS(CHR$(6%)+CHR$(9%)+CHR$(E%)),3%),4%) !RETURN ERROR MESSAGE FUNCTION. 10200 DEF FNP$(P%,Q%)=CVT$$('['+NUM$(P%)+','+NUM$(Q%)+']',2%) !MAKE A PACKED [P,PN] PRINT STRING. 19000 ! ! E R R O R R O U T I N E ! 19010 IF ERR=28% THEN RESUME 8000 !GETOUT IN A HUYRRY IF CTRL/C TRAP. 19020 IF ERL=2040 THEN PRINT Q3$;FNE$(ERR) \RESUME 2040 !SOME SORT OF ERROR IN FILENAME STRING SCAN SYS() CALL-TRY AGAIN. 19030 IF ERL=2110% AND ERR=52% THEN P1%=255% \ RESUME 2120% !AN '*' FOR PROJ# WHEN SELECTIVE-PRIVELEGED USER. 19040 IF ERL=2120% AND ERR=52% THEN P0%=255% \ RESUME 2130% !SAME AS PREVIOUS LINE EXCEPT FOR PROG#. 19050 IF ERL=2210% AND ERR=52% THEN P0%=255% \S9%=0% \RESUME 2400 !* FOR NUMBER BY GROUP LEADER ==> ALL RATHER THAN SELECTIVE. 19060 IF ERL=6010% THEN PRINT#1%, Q3$;FNP$(M%(8%),M%(7%));' -- ';FNE$(ERR) \M1%(0%)=-1% \L%=L%+2% \RESUME 6020 !AN ERROR WHILE TRYING TO DO THE ACCOUNT DUMP SYS() CALL. 19100 PRINT FNE$(ERR);' AT LINE';ERL \RESUME 8000 !TEMPORARY LINE FOR OTHER STUFF. 32767 END