.TITLE UPDATE -- ACCOUNT FILE DISK USAGE UPDATE .IDENT/V02XA/ ; ; PROGRAM NAME : U P D A T E . M A C ; DATE : SEPTEMBER 10, 1977 ; ; BY : JAMES G. DOWNWARD ; KMS FUSION, INC. ; ANN ARBOR, MICH 48104 ; 313-769-8500 ; ; ; 30-SEP-78 RJDK CORRECTED FOR BIGER DISKS WITH LARGER BITMAPS ; THAN RK05'S. CORRECTED FOR FAILURE WHEN MORE ; THAN 63. MAPPING POINTERS USED IN MAP REGION ; AND FOR MULTIPLE HEADERS(PREV LATER THAN FIRST ; WERE IGNORED). ; ; 16-JUL-79 JGD SEND DATA OFF TO LOG... IF PROPER BITS SET IN ; $ACMSK. ALLOW 'UPD ' TO BE ; EQUIVALANT TO 'UPD SY:[UIC]' ; ; ; .MCALL DIR$,OPEN$W,OPNS$R,READ$,CLOSE$,WAIT$,HMBOF$ .MCALL FSRSZ$,FDBDF$,FDAT$A,FDRC$A,FDBK$A .MCALL FDOP$A,FDBF$A,NMBLK$,FHDOF$,DEF$L .MCALL CALL,RETURN,PUT$,ALUN$,GTSK$,EXIT$S,ALTP$S .MCALL SDAT$,USTP$,RQST$,GTIM$,UCBDF$,TCBDF$ .MCALL GMCR$,OPEN$U,QIO$,WTSE$S,CALLR,MRKT$ ; UCBDF$ ; DEFINE UCB OFFSETS TCBDF$ ; DEFINE TCB OFFSETS ; ;+ ; THIS TASK WILL UPDATE THE ACCOUNT FILE TO REFLECT THE NUMBER OF ; FILES AND THE NUMBER OF BLOCKS USED, ON A USER BY USER BASIS. ; THE SYNTAX IS ; UPD DEV:[UIC] ; OR ; UPD DEV:[UIC]PASSWORD/UP ; OR ; UPD ; ; IF THE FIRST FORM IS USED, ANY USER MAY USE THE COMMAND TO FIND OUT ; THE CURRENT STATUS OF HIS DISK BLOCK USAGE. IN THIS CASE ; THE ACCOUNT FILE IS NOT UPDATED. IF THE SECOND FORM IS USED THE ; CORRECT PASSWORD FOR THE ACCOUNT(UP TO 6 CHARACTERS) AND THE SWITCH ; /UP (FOR UPDATE) MUST BE USED. ONLY A USER WHOSE LOGON UIC IS ; PRIVLEGED OR WHOSE TERMINAL IS PRIVLIGED MAY USE THIS COMMAND. ; WHEN ISSUED, IT COMPUTES THE TOTAL BLOCK USAGE AND THE NUMBER OF ; FILES USED FOR THE SPECIFIED DEVICE AND [UIC], AND THEN ; OPENS THE ACCOUNT FILE [0,0]RSX11.SYS, AND FINDS THE ACCOUNT ; BY MATCHING THE [UIC] AND PASSWORD. WARNING!! IT IS POSSIBLE ; THIS WAY TO UPDATE THE ACCOUNT INCORRECTLY IF THE WRONG DISK IS ; SPECIFIED. THIS IS NOT A SERIOUS PROBLEM SINCE THE PRIVLEGED ; COMMAND SYNTAX IS MENT TO BE USED ONLY IN AN INDIRECT COMMAND ; FILE TO PERIODICALLY UPDATE THE ACCOUNT FILE, OR TO BE RUN ; BY BYE EVERY TIME A NONPRIVLEGED USER LOGS OFF. THE LAST FORM ; IS FOR USER CONVENIENCE. A SIMPLE 'UPD' AT TI: WILL PROCUDE ; A TOTAL FILE AND BLOCK USED SUMMARY. ; TKB ; TKB>UPDATE/PR/MM=UPDATE,MCR/LB:ACTFIL ; TKB>MCR/LB,[1,1]EXELIB/LB,[1,54]RSX11M.STB ; TKB>/ ; ENTER OPTIONS: ; TASK=...UPD ; TKB>STACK=100 ; TKB>PRI=85 ; TKB>// ;- ; TTYLUN=4 TTYEFN=4 LUN1=1 EFN1=1 LUN2=2 EFN2=2 LUN3=3 EFN3=3 ; ; ERROR MESSAGES ; ER1: .ASCIZ <15><12>/UPD -- SYNTAX ERROR/ ER2: .ASCIZ <15><12>/UPD -- BAD DIRECTORY NAME/ .EVEN ER3: .ASCII <15><12>/UPD -- DISK / DTYP: .ASCII / / .ASCII / ERROR / DNUM: .ASCIZ / / ER4: .ASCIZ <15><12>/UPD -- ACCOUNT NOT UPDATED, ACCOUNT FILE BUSY OR LOCKED/ ER5: .ASCIZ <15><12>/UPD -- ACCOUNT FILE READ ERROR, GET HELP!!/ ER6: .ASCIZ <15><12>/UPD -- ACCOUNT FILE WRITE ERROR, GET HELP!!/ ER7: .ASCIZ <15><12>/UPD -- ACCOUNT NOT FOUND/ ER8: .ASCIZ <15><12>/UPD -- PRIVLEGE VIOLATION/ .EVEN ; USR: .ASCII <15><12>/AT END OF TERMINAL SESSION/ DEV: .ASCII <15><12> DSK: .ASCII / / UIC: .ASCII / HAS / BLOCKS: .ASCII / BLOCKS AND / FILES: .ASCIZ / FILES/ PASWRD: .ASCII / / .EVEN DEVCNT: .WORD 0 ; NUMBER OF BYTES IN DEVICE STRING UICCNT: .WORD 0 ; NUMBER OF BYTES IN UIC STRING PASCNT: .WORD 0 ; NUMBER OF BYTES IN PASWORD STRING UPDFLG: .WORD 0 ; FLAG(=1) TO INDICATE ACCOUNT SHOULD BE UPDATED TEMP: .WORD 0 ; RESERVED FOR USE WWITH OPENIG ACCOUNT FILE ENTRY: .WORD 0 ; STORAGE FOR ENTRY POINT INTO ACCOUNT FILE COUNT: .WORD 0 ; STORAGE FOR THE NUMBER OF WORDS READ FROM ACCOUNT FILE OPNFLG: .WORD 0 ; FLAG(=1) TO INDICATE THE ACCOUNT FILE IS OPEN OPNERR: .WORD 0 ; FLAG(>=1) TO INDICATE AN ERROR OCCURED OPENING REDERR: .WORD 0 ; FLAG SET(=1) TO INDICATE A ACCOUNT FILE READ ERROR WRTERR: .WORD 0 ; FLAG SET)=1) TO INDICATE AN ACCOUNT FILE WRITE ERROR EOLFLG: .WORD 0 ; FLAG SET TO INDICATE EOL FOUND RIGHT AFTER UPD TIMBUF: .BLKW 8. ; TIME BUFFER ; THE NEXT 13. WORDS MUST NOT BE SEPERATED (SEND BUFFER TO LOG...) SNDBUF: .WORD 7. ; TYPE OF PACKET SENT(RECORD IDENTIFIER) .BLKW 12. ; REST OF SEND DATA PACKET ; THE FORMAT OF THE SEND DATA PACKET IS ; 7.,HR,MIN,SEC,ACNT #,SYSTEM DEVICE(4 BYTES),FILES USED,BLOCKS USED, BLOCKS ALLOCATED ; ; ; ODPB: QIO$ IO.WVB,TTYLUN,TTYEFN,,,, ; TI: OUTUPT DPB GETTIM: GTIM$ TIMBUF ; GET TIME DPB RQSTLG: RQST$ LOG... ; REQUEST LOGTSK USTPLG: USTP$ LOG... ; UNSTOP LOGTSK SNDDAT: SDAT$ LOG...,SNDBUF ; SEND DATA TO LOGTSK ; FDPB: QIO$ IO.RVB,LUN2,EFN2,,IOSB,,<$ACTBF,$BFLEN,,,1> ; DBP FOR [0,0]RSX11.SYS IOSB: .BLKW 2 ; I/O STATUS BOCK MKT: MRKT$ EFN2,100.,1 ; WAIT FOR 100 TICKS GMCR: GMCR$ BUFF=GMCR+2 ; BUFFER FOR ALL TI: I/O ; ; ; ;+ ; THIS SECTION CONTAINS THE FILE DESCRIPTOR BLOCKS AND ; ASSOCIATED INFORMATION. ;- ; FSRSZ$ 1 ;ONE RECORD CONTROLLED FILE FHDOF$ DEF$L ;DEFINE INDEX FILE OFFSETS HMBOF$ DEF$L ;DEFINE HOME BLOCK OFFSETS ; ; ; FDB FOR DIRECTORY FILE (*.DIR) ; FDB1:: FDBDF$ FDAT$A R.FIX,,1000 FDRC$A FD.RWM!FD.RAN!FD.PLC FDBK$A WORKBU,1000,,EFN1,BKST1 FDOP$A LUN1,DSPT1,FNB1 FDBF$A EFN1 ; FNB1:: NMBLK$ ,DIR,0,SY,0 ; ; FDB FOR INDEX FILE (INDEX.SYS) ; FDB2:: FDBDF$ FDAT$A R.FIX,,1000 FDRC$A FD.RWM!FD.RAN!FD.PLC FDBK$A WORKBU,1000,,EFN3,BKST2 FDOP$A LUN3,DSPT2,FNB2 FDBF$A EFN3 ; FNB2: NMBLK$ INDEXF,SYS,0,SY,0 ; DATA SET BLOCK FOR DIRECTORY FILE ; DSPT1:: .WORD DNSZE .WORD DNSTR .WORD DSTRSZ .WORD DSTR1 .WORD SSZE1 .WORD STR1 ;+ ; DATA SET BLOCK FOR INDEX FILE ;- DSPT2: .WORD DNSZE .WORD DNSTR .WORD DSTRSZ .WORD DSTR1 .WORD SSZE2 .WORD STR2 ; BKST1: .BLKW 2 BKST2: .BLKW 2 ; .NLIST BIN DSTR1: .ASCII %[0,0]% DSTRSZ=.-DSTR1 .EVEN ; STR1: .ASCII %000000% SSZE1=.-STR1 .EVEN ; STR2: .ASCII %INDEXF% SSZE2=.-STR2 .EVEN ; STR3: .BLKB 9. SSZE3=.-STR3 .EVEN ; ; DNSTR: .ASCII %SY0:% DNSZE=.-DNSTR .EVEN .LIST BIN ;+ ; THIS SECTION CONTAINS THE BLOCK BUFFERS AND WORK BUFFERS ;- ; WORKBU: .BLKW 256. WRKBU: .BLKW 256. ; ; ; ; .EVEN ; ASGTTY: ALUN$ TTYLUN,TI,0 GTSK: GTSK$ WORKBU ; ; TTIOST: .BLKW 2 TTYBUF: .BLKW 12. NENTRY: .BLKW 1 TMP: .BLKW 2 NBLOCK: .BLKW 1 ; ; BUF: .BLKW 18. INXFHD: .WORD 0 ; POINTER TO START OF FILE HEADERS ; RJDK ; ; ; ;+ ; ASSEMBLY PARAMETERS ;- ; ; UPDATE: DIR$ #ASGTTY ; ASSIGN LUN 2 TO TI DIR$ #GMCR ; GET MCR COMMAND LINE DIR$ #GETTIM ; GET THE TIME MOV TIMBUF+6,SNDBUF+2 ; SET HOUR MOV TIMBUF+10,SNDBUF+4 ; SET MIN MOV TIMBUF+12,SNDBUF+6 ; SET SEC ALTP$S ,#60. ; RUN AT A LOWER PRIORITY(=60.) WHILE COUNTING BLOCKS AND FILES BCS 1$ ; IF ERRORS(CARRY SET) EXIT BR 10$ ; IF NO ERRORS, THEN CONTINUE 1$: MOV #ER1,R0 ; PRINT COMMAND ERROR MESSAGE CALL WRIT ; JMP EXIT ; AND EXIT 10$: CALL DECODE ; DECODE THE COMMAND LINE CALL BLOCK ; FIND THE NUMBER OF BLOCKS AND FILES ON THE DIRECTORY TST UPDFLG ; IS THE ACCOUNT FILE TO BE UPDATED BEQ EXIT ; NO, THEN EXIT MOV $TKTCB,R0 ; GET TASK'S TCB ADDRESS MOV T.UCB(R0),R1 ; GET UCB ADDRESS OF TI: CMPB U.LUIC+1(R1),#10 ; IS UIC PRIVLIGED BLOS 15$ ; YES, SKIP OVER BIT #U2.PRV,U.CW2(R1) ; PERHAPS TERMINAL IS PRIVLEGED BUT UIC >[10,XXX] BNE 15$ ; YES TERMINAL IS PRIVLEGED SO SKIP OVER MOV #ER8,R0 ; NO, PRIVLEGE VIOLATION CALL WRIT ; PRINT ERROR MESSAGE BR EXIT1 ; AND EXIT 15$: ALTP$S ; ALTER PRIORITY BACK TO DEFAULT PRIORITY(=85.) CALL OPEN ; OPEN THE ACCOUNT FILE(RSX11.SYS) FOR UPDATE CLC ; CLEAR CARRY JUST IN CASE CALL FIND ; FIND THE ACCOUNT GIVEN THE UIC AND PASSWORD TST REDERR ; WAS THERE AN ACCOUNT FILE READ ERROR? BEQ 20$ ; NO SKIP AROUND MOV #ER5,R0 ; YES, PRINT ERROR MESSAGE CALL WRIT ; PRINT IT 20$: TST WRTERR ; WAS THERE AN ERROR WRITING TO THE ACCOUNT BEQ 30$ ; NO, SKIP AROUND MOV #ER6,R0 ; YES, PRINT ERROR MESSAGE CALL WRIT ; AT USER'S TERMINAL 30$: TST OPNFLG ; IS ACCOUNT FILE OPEN? BEQ EXIT ; NO, JUST EXIT CLOSE$ #$ACTFL ; YES, SO WE MUST CLOSE ACCOUNT FILE FIRST EXIT: TST UPDFLG ; SHOULD UPDATE MESSAGE BE PRINTED? BEQ EXIT0 ; NO, BRANCH MOV #USR,R0 ; YES CALL WRIT ; PRINT MESSAGE BIT #200,$ACMSK ; SHOULD WE SEND OF DATA PACKET TO LOGTSK BEQ EXIT1 ; IF EQ, NO DIR$ #SNDDAT ; SEND OFF DATA BCS EXIT1 ; IF CS, IT IS NOT INSTALLED OR WORSE, SO GIVE UP DIR$ #USTPLG ; TRY UNSTOPPING IT BCC EXIT1 ; WE GOT IT UNSTOPPED SO EXIT DIR$ #RQSTLG ; AS A LAST DITCH EFFORT, TRY REQUESTING LOG... TO RUN BR EXIT1 ; BRANCH OVER EXIT0: MOV #DEV,R0 ; PRINT OUT THE NUMBER OF CALL WRIT ; BLOCKS AND FILES IN USE BY USER EXIT1: EXIT$S ; EXIT DECODE: MOV #BUFF,R0 ; GET THE TI: INPUT BUFFER ADD #2,R0 ; POINT TO WHERE WE EXPECT COMMAND 2$: CALL $GNBLK ; $GNBLK IS IN MCR.OLB ; R1 = # OF BLANKS PASSED OVER ; CARRY IS SET IF EOL IS FOUND ; R0 = ADDRESS OF TI: BUFFER, INCREMENTED AFTER EACH CALL ; R2 = THE CHARACTER FOUND ; BCS 6$ ; EOL IS A SYNTAX ERROR HERE BCC 301$ ; IF NO EOL, SKIP INC EOLFLG ; SHOW EOL FOUND AT START OF LINE 301$: ; TST R1 ; HAVE WE PAST BY THE SEPERATING SPACE BEQ 2$ ; NO, LOOP AGAIN MOV #DSK,R3 ; GET ADDRESS OF STORAGE FOR DISK CHARACTERS TST EOLFLG ; IS EOL FLAG SET BNE 302$ ; IF YES SKIP NEXT TEST CMPB R2,#'[ ; IS FIRST CHARACTER A '[' BNE 4$ ; IF NE, NO, PROCEED AS NORMAL 302$: MOV #3,DEVCNT ; ELSE SET CHARACTER COUNTER MOVB #'S,(R3)+ ; AND MOV IN AN SY MOVB #'Y,(R3)+ ; INTO DEVICE STRING MOVB #':,(R3)+ ; SINCE WE ASSUME THE USER WANTS SY: TST EOLFLG ; IS EOLFLG SET BNE 305$ ; IF YES SKIP MOV #UIC,R3 ; SET UP FOR UIC PARSE MOVB R2,(R3)+ ; AND STUF IN THE '[' INC UICCNT ; BUMP UP COUNTER BY ONE BR 8$ ; AND GO DECODE THE REST OF THE UIC STRING 305$: ; REF LABLE MOV R2,-(SP) ; SAVE R2 MOV R3,-(SP) ; SAVE R3 MOV $TKTCB,R2 ; GET OUR TASK HEADER MOV T.UCB(R2),R2 ; GET OUR UCB ADDRESS MOV U.LUIC(R2),R3 ; SET BINARY UIC MOV #UIC,R2 ; SET OUTPUT STRING ADDRESS MOV #1,R4 ; SET TO LEAVE IN ZEROS IF ANY CALL .PPASC ; CONVERT TO ASCII STRING MOV #9.,UICCNT ; SET CHARACTER COUNT MOV (SP)+,R3 ; RESTORE R3 MOV (SP)+,R2 ; RESTORE R2 BR 16$ ; GO DISPLAY BLOCK COUNT 4$: CMPB R2,#': ; IS FIRST CHARACTER A COLON BEQ 6$ ; YES, WELL IT SHOULDN'T, ERROR MOVB R2,(R3)+ ; NO, START FILLING IN DISK UNIT INC DEVCNT ; INCREMENT COUNTER 5$: CALL $GNBLK ; BCS 6$ ; EOL IS ERROR MOVB R2,(R3)+ ; INSERT NEXT CHARACTER INC DEVCNT ; AND BUMP UP COUNTER CMPB R2,#': ; A COLON FOUND YET? BEQ 7$ ; YES BRANCH BR 5$ ; NO, LOOP 6$: JMP SYNERR ; ERROR EXIT POINT 7$: MOV #UIC,R3 ; NOW GET READY TO GET THE UIC CALL $GNBLK ; GET THE NEXT NON BLANK CHARACTER BCS 6$ ; EOL IS AN ERROR CMPB R2,#'[ ; IT HAD BETTER BE A "[" BNE 6$ ; NOT A "[", SYNTAX ERROR MOVB R2,(R3)+ ; ITS OK, STUFF IT INC UICCNT ; INCREMENT COUNTER OF # BYTES IN UIC STRING 8$: CALL $GNBLK ; GET ANOTHER CHARACTER BCS 6$ ; EOL ILLEGAL MOVB R2,(R3)+ ; STUFF IT INC UICCNT ; INCREMENT COUNTER CMPB R2,#'] ; IS IT A "]" BNE 8$ ; NOT A "]" LOOP SOME MORE MOV #PASWRD,R3 ; NEXT FILL IN PASSWORD 10$: CALL $GNBLK ; GET A CHARACTER BCS 101$ ; EOL OK NOW CMPB R2,#'/ ; IS THE UPDATE SWITCH COMING? BEQ 12$ ; YES, GO SEE MOVB R2,(R3)+ ; NO, GO STUFF PASSWORD INC PASCNT ; INCREMENT THE COUNTER FOR THE NUMBER OF BYTES ; IN A PASSWORD. CMP #6,PASCNT ; IN NO CASE SHOULD THERE BE MORE THAN 6 CHARACTERS BEQ 11$ ; WE HAVE 6 CHARACTERS, THE NEXT BETTER BE A " BR 10$ ; GET ANOTHER CHARACTER 101$: TST PASCNT ; ARE ANY PASSWORD LETTERS PRESENT BNE 6$ ; YES, SYNTAX ERROR IF EOL BEFORE "/UP" BR 16$ ; NO, JUST REPORT THE FILE AND BLOCK USAGE 11$: CALL $GNBLK ; GET NEXT CHARACTER BCS 6$ ; NO EOL UNTIL "/UP" IS FOUND CMPB R2,#'/ ; DID WE FIND A "/"? BNE 6$ ; NO, SYNTAX ERROR 12$: CALL $GNBLK ; GET ANOTHER CHARACTER BCS 6$ ; NO EOL ALLOWED CMPB R2,#'U ; IS IT UPDATE SWITCH? BEQ 15$ ; YES, GO DO IT BR 6$ ; NO SYNTAX ERROR 15$: INC UPDFLG ; SET UPDATE FLAG 16$: MOV #DSK, ; SET UP CORRECT DEVICE FOR DIRECTORY FILE ; GGGMMM.DIR;1 MOV DEVCNT,DSPT1 ; AND SET THE CORRECT BYTE COUNT MOV #DSK, ; SET UP CORRECT DEVICE FOR INDEX FILE(INDEXF.SYS) MOV DEVCNT,DSPT2 ; AND SET THE CORRECT BYTE COUNT MOV #UIC,R0 ; SET ADDRESS OF UIC ENTRY ADD UICCNT,R0 ; OFFSET TO POINT TO LAST NUMERIC ENTRY DEC R0 ; BY POINTING TO "]" AND BACKING UP ONE CHARACTER MOV #STR1,R1 ; GET ADDRESS OF DIRECTORY STRING ADD #6,R1 ; POINT TO LAST POSSIBLE NUMERIC ENTRY 17$: CMPB #',,-(R0) ; IS IT A ","? BEQ 20$ ; YES, GO GET GROUP CODE MOVB (R0),-(R1) ; NO, MOVE IN MEMBER CODE ONE BYTE AT A TIME BR 17$ ; AND LOOP TILL COMMA FOUND 20$: MOV #STR1,R1 ; RESET POINTER TO GROUP CODE IN DIRECTORY STRING ADD #3,R1 ; AND POINT TO THE LAST NUMBER (GROUP) 25$: CMPB #'[,-(R0) ; IS IT A "["? BEQ 30$ ; YES, ALL DONE MOVB (R0),-(R1) ; NO, SO MOVE IN GROUP CODE-(IN REVERSE) BR 25$ ; AND LOOP TILL DONE 30$: RETURN ; ALL DONE ;+ ; ENTER HERE AFTER COMMAND STRING HAS BEEN INTERPRETED ; READ DIRECTORY FILE BLOCK-BY-BLOCK AND LOAD EACH EIGHT WORD ; ENTRY INTO THE BUFFER, RETAINING THE LAST 5 WORDS OF ; EACH ENTRY. ;- BLOCK: OPNS$R #FDB1,,,#FD.RWM ;OPEN DIRECTORY FILE(NNNMMM.DIR;1) BCC 17$ ;ERROR? CALL DSKOPN ;YES--INFORM USER JMP EXIT 17$: MOV #1, ;NO--SET TO 1ST VBN OPNS$R #FDB2,,,#FD.RWM ;OPEN INDEX FILE BCC 18$ ;ERROR? CALL DSKOPN ;YES--INFORM USER 18$: MOV #3, ;SET UP TO READ HOME BLOCK(SET EOF BLOCK #=30) MOV #2, ;SET VBN=2 READ$ #FDB2,#WORKBU ;READ HOME BLOCK(INDEXF.SYS) BCC 19$ ;ERROR? CALL DSKRED ;YES--INFORM USER 19$: WAIT$ #FDB2 ;NO--CONTINUE MOV ,R0 ;GET INDEX BIT MAP SIZE ADD #3,R0 ;AND FIND VBN FOR INDEX FILE MOV R0,INXFHD ; SAVE START OF FILES FOR LATER ; RJDK MOV R0, INC R0 MOV R0, ;SET UP VBN POINTER FOR GETBLOCK CALL GETBLK ;FIND # BLOCKS IN INDEX FILE INC R2 MOV R2, CLR NBLOCK ;ZERO BLOCK COUNTER CLR NENTRY ;ZERO NUMBER OF ENTRIES 20$: READ$ #FDB1,#WORKBU ;READ A BLOCK BCC 21$ ;ERROR? CMPB #IE.EOF,FDB1+F.ERR ;MAYBE--END OF FILE? BEQ 22$ ;YES MOV #FDB1,R0 ;NO--REPORT ERROR CALL DSKRED JMP 29$ 21$: WAIT$ #FDB1 CALL LOAD ;LOAD THE ENTRIES IN TO THE BUFFER BR 20$ ;READ NEXT BLOCK 22$: MOV NENTRY,R1 CLR R2 ; SUPRESS ZEROS MOV #FILES,R0 CALL $CBDMG ;CONVERT # FILES TO ASCII 29$: MOV NBLOCK,R1 MOV #BLOCKS,R0 CLR R2 ; SUPRESS ZEROS CALL $CBDMG ;CONVERT # BLOCKS TO ASCII CLOSE$ #FDB1 CLOSE$ #FDB2 RETURN ; RETURN TO MAIN LINE CODE SYNERR: MOV #ER1,R0 ; PRINT SYNTAX ERROR MESSAGE CALL WRIT ; JMP EXIT1 ; AND EXIT ; XFR: CMPB #' ,(R1) ;CHARACTER A SPACE ? BEQ 1$ ;YES--DON'T X-FER MOVB (R1),(R2)+ ;NO--PUT INTO DISPLAY BUFFER 1$: TSTB (R1)+ ;BUMP TO NEXT CHARACTER SOB R5,XFR ;MORE CHARACTERS? RETURN ; UICXFR: TST R3 BEQ 2$ 1$: MOVB #'0,(R1)+ SOB R3,1$ 2$: MOV #TMP,R2 3$: MOVB (R2)+,(R1)+ SOB R4,3$ RETURN ; ;+ ; THIS SUBROUTINE WILL DETERMINE THE NUMBER OF BLOCKS ALLOCATED ; BY A SPECIFIC FILE. UPON ENTRY THE VBN MUST BE SET (FDB2+F.BKVB+2) ; FOR THE FILE HEADER BLOCK WITHIN THE INDEX FILE. ; VBN = 1ST WORD OF FILE ID + N ;- GETBLK: MOV R0,-(SP) CLR R2 ;ZERO BLOCK COUNTER 100$: ; REF LABEL FOR MULTIHEADER SUPPORT ; RJDK READ$ #FDB2,#WRKBU ;READ FILE HEADER BCC 1$ ;ERROR? CALL DSKRED ;YES--INFORM USER BR 20$ ;AND EXIT 1$: WAIT$ #FDB2 ;NO--CONTINUE MOV #WRKBU,R0 MOVB 1(R0),R1 ;GET MAP AREA OFFSET ASL R1 ;AND CONVERT TO A BYTE OFFSET ADD R1,R0 ;ADJUST POINTER TO MAP AREA CLR R1 ; ; RJDK BISB M.USE(R0),R1 ; GET #WORDS OF RETRIEVAL PTRS ; RJDK ASR R1 ;EACH PTR CONSISTS OF 2 WORDS ;**-1 BLE 20$ ;0 BLOCKS ALLOCATED--EXIT!! ADD #M.RTRV,R0 ;MOVE TO START OF RETRIEVAL PTRS 2$: MOVB 1(R0),R3 ;GET BLOCK COUNT-1 BIC #177400,R3 ;CLEAR UPPER BYTE (SBE) INC R3 ADD R3,R2 ;ADD # BLKS TO TOTAL CMP (R0)+,(R0)+ ;MOVE TO NEXT RETRIEVAL PTR SOB R1,2$ ;MORE POINTERS? MOV #WRKBU,R0 ; TEDIOUSLY GET WORD WHICH MAY CONTAIN ; RJDK MOVB 1(R0),R1 ; FID FOR CONTINUATION HEADER ; RJDK ASL R1 ; ; RJDK ADD R1,R0 ; ; RJDK MOV M.EFNU(R0),R1 ; AT LAST ; RJDK BEQ 20$ ; ZERO AT END SO DONE ; RJDK DEC R1 ; COMPENSATE FOR POINTER BEING TO 1:1 ; RJDK ADD INXFHD,R1 ; AND MAKE CORRECT BLOCK # ; RJDK MOV R1, ; ; RJDK BR 100$ ; AND DO NEXT HEADER ; RJDK 20$: MOV (SP)+,R0 RETURN ;+ ; THIS SUBROUTINE WILL SEARCH THROUGH EACH 8 WORD ENTRY CONTAINED ; IN THE INDEX FILE, DETERMINE IF THE FILE IS STILL EXISTANT (THE ; FIRST WORD IS NON-ZERO). ; THE LAST 5 WORDS OF EACH ENTRY (FILE NAME, EXTENTION, AND VERSION ; NUMBER) ARE RETAINED IN THE BUFFER (BLKBUF). ; ALSO, AN ADDITIONAL WORD CONTAINING THE VBN OF THE FILE HEADER IS ; STORED AS THE 6TH WORD. ;- LOAD: MOV #32.,R4 ;# ENTRIES/BLOCK IN DIRECTORY FILE MOV #WORKBU,R0 ;SET PTR TO 1ST ENTRY 1$: TST (R0) ;ENTRY STILL ACTIVE? BEQ 11$ ;NO--MOVE TO NEXT ENTRY MOV (R0),R2 ;COMPUTE VBN ; ADD #3,R2 ; BUF FIRST OFFSET IT BY 3(WHY I DON'T K; RJDK ADD INXFHD,R2 ; ; RJDK DEC R2 ; POINT TO FILE HEADER OFFSET FROM FID1:; RJDK MOV R2, ;LOAD THE VBN INTO THE FDB ;**-1 CALL GETBLK ;GET THE NUMBER OF BLOCKS ADD R2,NBLOCK ;ADD TO RUNNING TOTAL INC NENTRY ;INCREMENT # ENTRIES 11$: ADD #20,R0 ;MOVE TO NEXT INDEX FILE ENTRY DEC R4 ;MORE ENTRIES? BLE 12$ ;NO JMP 1$ ;YES 12$: RETURN ;+ ; ERROR ROUTINE FOR DISK ERRORS ;- ; DSKOPN: MOV #"OP,DTYP MOV #"EN, BR CON1 DSKRED: MOV #"RE,DTYP MOV #"AD, BR CON1 DSKWRT: MOV #"WR,DTYP MOV #"TE, CON1: MOVB F.ERR(R0),R3 ;PICK UP ERROR BYTE BMI 1$ CLR R3 1$: NEG R3 ;TAKE 2'COMPLEMENT MOV #DNUM,R5 CLR R2 DIV #12,R2 SWAB R3 ADD R2,R3 ADD #30060,R3 MOV R3,(R5) MOV #ER3,R0 ; WRITE OUT ERROR MESSAGE CALL WRIT ; ERRRET: JMP EXIT1 ; ; ; ; ;+ ; *** - WRIT - WRITE TERMINAL MESSAGE ; ; INPUT: ; R0 - MESSAGE ADDRESS ; ;- WRIT: MOV R0,R1 ; COPY BUFFER ADDRESS 10$: TSTB (R1)+ ; END OF MESSAGE? BNE 10$ ; NO, LOOP TILL END SUB R0,R1 ; COMPUTE LENGTH MOV #ODPB,R4 ; GET OUTPUT DPB ADDRESS MOV R0,Q.IOPL(R4) ; SET BUFFER ADDRESS MOV R1,Q.IOPL+2(R4) ; SET BUFFER LENGTH CALLR QIO ; WRITE IT OUT ;+ ; *** - QIO - ISSUE QIO ; ; INPUT: ; R4 - DPB ADDRESS ;- QIO: DIR$ R4 ; ISSUE QIO BCS 10$ ; ERROR MOVB Q.IOEF(R4),R5 ; GET EVENT FLAG TO WAIT ON WTSE$S R5 ; AND WAIT 10$: RETURN ; ;+ ; *** - OPEN - OPEN ACCOUNT FILE FOR UPDATE([0,0]RSX11.SYS] ; AN ATTEMPT WILL BE MADE TO OPEN FILE UP TO 5 TIMES ; IN CASE THE FILE IS IN USE. ;- OPEN: CLR OPNERR ; SHOW NO ERRORS TO START WITH 10$: OPEN$U #$ACTFL,,,#FD.RWM ; TRY AND OPEN FILE FOR UPDATE BCC 40$ ; IF NO ERRORS EXIT SUBROUTINE CMP OPNERR, #5. ; OTHERWISE CHECK THE NUMBER OF TIMES TRIED TO OPEN FILE BLT 20$ ; IF LESS THAN OR EQUAL TO 5 TIME, WAIT 1 SEC AND TRY AGAIN MOV #ER4,R0 ; IF TRIED 5 TIMES, PRINT ERROR MESSAGE AND EXIT CALL WRIT ; PRINT IT AT TI: JMP EXIT ; AND EXIT 20$: DIR$ #MKT ; LETS WAIT 1 SECOND AND TRY AGIAN WTSE$S #EFN1 ; AND WAIT ON EVENT FLAG EFN1 INC OPNERR ; INCREMENT THE NUMBER OF TIMES TRIED TO OPEN FILE BR 10$ ; AND TRY AGAIN 40$: INC OPNFLG ; SET FILE OPEN FLAG CLR OPNERR ; SET NO ERROR RETURN ; GO BACK TO MAINLINE CODE ;+ ; ***FIND - READ ACCOUNT INFORMATION INTO THE BUFFER AND ; SEE IF PASSWORD AND NAME MATCH ; EACH BUFFER(ACTBF) IS 512 BYTES LONG AND CONTAINS 4 ; USER ACCOUNT BLOCKS ; ;- FIND: MOV #FDPB,R4 ; GET FILE DPB ADDRESS MOV R4,TEMP ; SAVE R4 FOR LATER MOV #1,Q.IOPL+10(R4) ; SET TO START AT VBN 1 CLR Q.IOPL+6(R4) ; 5$: CALL QIO ; READ IN THE BLOCK MOV IOSB+2,COUNT ; GET COUNT OF WORDS READ BEQ 50$ ; IF ZERO WORDS READ, TEST FOR END OF FILE MOV #$ACTBF,R0 ; GET BUFFER ADDRESS 10$: MOV R0,ENTRY ; SAVE ENTRY ADRESS FOR LATER, WE'LL NEED IT CALL MATCH ; DO NAME AND PASSWORD MATCH? TST UPDFLG ; IF MATCH FOUND, UPDFLG=0 BEQ 100$ ; YES, MATCH FOUND, GO WRITE OUT BLOCK MOV ENTRY,R0 ; RESTORE ENTRY, SO WE CAN STEP THROUGH THE ACCOUNT ; BUFFER. ADD #A.LEN,R0 ; POINT TO NEXT ENTRY SUB #A.LEN,COUNT ; COMPUTE WORDS LEFT IN BUFFER BHI 10$ ; IF STILL MORE TO PROCESS IN THIS BUFFER ; LOOP BACK AND CHECK NEXT ACCOUNT 50$: CMPB #IE.EOF,IOSB ; OTHERWISE CHECK FOR END OF FILE BEQ 60$ ; YES, EOF FOUND AND WE ARE DONE FOR NOW TSTB IOSB ; BE SURE WE DON'T HAVE ANY READ ERRORS BMI 54$ ; A READ ERROR FOUND, SET CARRY BEFORE EXITING MOV TEMP,R4 ; RESTORE R4 ADD #$BFLEN/512.,Q.IOPL+10(R4) ; NO ERRORS, SO POINT TO NEXT VBN ADC Q.IOPL+6(R4) ; BR 5$ ; READ IN A NEW BUFFER 54$: INC REDERR ; LET THE MAINLINE CODE KNOW ITS A READ ERROR 55$: SEC ; SET CARRY AS AN ERROR FLAG BR 65$ ; SKIP 60$: TST UPDFLG ; DID WE FIND A MATCH BEQ 67$ ; YES, RETURN MOV #ER7,R0 ; PRINT OUT MESSAGE "INVALID ACCOUNT" CALL WRIT ; ON TERMINAL 65$: RETURN ; 67$: INC UPDFLG ; RESET UPDATE FLAG FOR LATER USE RETURN ; 70$: INC WRTERR ; LET THE MAINLINE CODE KNOW ITS A WRITE ERROR BR 55$ ; SET CARRY AND EXIT 100$: MOV TEMP,R4 ; RESTORE R4 (DPB ADDRESS) MOV #IO.WVB,2(R4) ; NOW GET SET TO WRIT OUT THE BLOCK JUST READ IN MOV IOSB+2,Q.IOPL+2(R4) ; SET COUNT OF BYTES TO WRITE BACK OUT CALL QIO ; WRITE OUT THE BLOCK MOV #IO.RVB,2(R4) ; RESTORE DPB MOV #$BFLEN,Q.IOPL+2(R4) ; AND LENGTH TSTB IOSB ; ANY ERRORS? BMI 70$ ; OH SHIT!!, SET CARRY, EXIT AND SALVAGE FILE IF POSSIBLE BR 60$ ; NO ERRORS, SO GO BACK TO MAINLINE CODE ;+ ; *** - MATCH -- MATCH THE UIC AND PASSWORD AGAINST THE UIC AND PASSWORD ; IN THE ACCOUNT FILE. IF A MATCH IS FOUND, UPDATE THE TOTAL ; NUMBER OF FILES AND BLOCKS USED BY THE ACCOUNT. OTHERWISE ; JUST EXIT. ;- MATCH: ADD #A.GRP,R0 ; POINT TO THE GROUP-MEMBER ENTRY IN THE ACCOUNT FILE MOV #STR1,R1 ; POINT R1 TO THE DECODED UIC STRING CLR R2 ; ZERO THE COUNTER 10$: CMPB (R0)+,(R1)+ ; DO THE CHARACTERS MATCH BNE 100$ ; NO, EXIT INC R2 ; YES, THEN ONE MORE CHARACTER MATCHED CMP #6.,R2 ; SIX MATCHES YET BEQ 20$ ; YES, THEN UIC'S MATCH, GO CHECK PASSWORD BR 10$ ; NO, THEN LOOP SOME MORE 20$: MOV #PASWRD,R1 ; POINT R1 TO FIRST ENTRY IN PASSWORD CLR R2 ; ZERO THE COUNTER 30$: CMPB (R0)+,(R1)+ ; DO THE CHARACTERS MATCH? BNE 100$ ; NO, THEN EXIT INC R2 ; YES, THEN ONE MORE CHARACTER MATCHED CMP #6,R2 ; HAVE ALL SIX CHARACTERS IN THE PASSWORD MATCHED? BEQ 40$ ; YES, WE HAVE THE RIGHT ACCOUNT, UPDATE IT BR 30$ ; NO, LOOP SOME MORE 40$: MOV ENTRY,R0 ; POINT TO FIRST ENTRY IN ACCOUNT FILE ADD #A.FILS,R0 ; POINT TO THE NUMBER OF FILES ENTRY IN THE ACCOUNT MOV NENTRY,(R0) ; INSERT IT INTO THE ACCOUNT MOV ENTRY,R0 ; POINT TO THE FIRST ENTRY IN THE ACCOUNT ADD #A.UBLK,R0 ; POINT TO THE NUMBER OF USED BLOCKS ENTRY MOV NBLOCK,(R0) ; INSERT IT INTO THE ACCOUNT CLR UPDFLG ; RESET THE UPDATE FLAG TO TELL THE MAINLINE ; CODE TO UPDATE THE ACCOUNT BLOCK. MOV ENTRY,R0 ; POINT TO START OF ACCOUNT BLOCK MOV A.ACN(R0),SNDBUF+10 ; SET ACCOUNT NUMBER IN SEND PACKET MOV ENTRY,R0 ; SET START OF ACCOUNT BLOCK ADD #A.SYDV,R0 ; POINT TO SYSTEM DEVICE ENTRY MOV (R0)+,SNDBUF+12 ; SET IN FIRST PART OF ASCII SYSTEM DEVICE NAME MOV (R0),SNDBUF+14 ; SET IN SECOND HALF OF SYSTEM DEVICE NAME. MOV NENTRY,SNDBUF+16; SET # FILES USED IN SEND PACKET MOV NBLOCK,SNDBUF+20; SET # BLOCKS USED IN SEND PACKET MOV ENTRY,R0 ; SET START OF ACCOUNT BLOCK MOV A.ABLK(R0),SNDBUF+22 ; SET # OF BLOCKS ALLOWED 100$: RETURN ; ALL DONE FOR NOW .END UPDATE