; ; .TITLE VFY .SBTTL DISK VERIFICATION UTILITY .IDENT /V01.1/ .ENABL LC .SBTTL PROGRAM DESCRIPTION ; ; PROGRAM TO VERIFY THE VOLUME_ID AND OWNER OF A DISK PACK ; ; Author: LARRY OWENS - 6/MAR/82 ; Last edit: Larry Owens, 20/Jun/83 - Fix "clean" exit to allow REEnter ; System: RT-11 v4 (?v3) ; ; The purpose of this utility program is to allow the user to view and/or ; verify the VOLUME_ID and OWNER of a random-access device. This utiltiy ; accepts a standard CSI command line which consists of one input device ; specification and three optional switches. The general command line is: ; ; *[ddu:][/V][/O][/Q] ; 1 2 3 4 ; ; Where: 1 is the random-access DEVICE specification ; 2 is the VOLUME_ID VERIFICATION switch ; 3 is the OWNER VERIFICATION switch ; 4 is the QUIET MODE switch ; ; You will note that there are no mandatory fields; all four ; of these fields have default values. These defaults are: ; ; 1) The default value for the DEVICE field is "DK:". NOTE: there is no ; filespec associated with this field. This is because this utility ; does a non-directory structured open for the device and then reads ; two 12-byte fields, containing the VOLUME_ID and OWNER data, at a ; fixed offset from the beginning (absolute block 0) of the device. ; If the user does specify a filespec in this field it is ignored. ; ; 2) The VOLUME_ID switch requests a verification of the VOLUME_ID data ; stored on the DEVICE (3) specified. If the VOLUME_ID switch is ; specified (/V) then this utility will prompt the user for the value ; to be compared with the data stored on the DEVICE (3) specified. If ; the two match exactly, then the verification is successful. Otherwise, ; the verification is not successful, and this utility will output the ; message "VFY-F-Volume ID Verification Error" followed by a Severe ; Error type exit. The VOLUME_ID field is 12 characters long and may ; contain embedded ASCII spaces. If the user does not specify a full ; 12 character value, then this utility will fill the remaining ; characters with ASCII spaces (this mimics the action of DUP with ; the INIT/VOLUME command). Note that this implies that a null string ; specification will be expanded to a value of 12 ASCII spaces (again, ; just like DUP). If the user specifies more than 12 characters, then ; the user is informed of the error and reprompted for the value. ; ; 3) The OWNER switch operates just like the VOLUME_ID switch except that ; it requests a verification of the OWNER data stored on the DEVICE (3) ; specified. If a verification is not successful, then the message ; "VFY-F-Owner Verification Error" will be output followed by ; a Severe Error type exit. ; ; 4) The QUIET switch disables the display of the VOLUME_ID and OWNER data ; retreived from the input DEVICE (1). The default mode is NOQUIET, in ; this case the data retreived from the input device is displayed on ; the console for the user to view. Any warning and/or error messages ; will always be displayed, regardless of the QUIET (/Q) switch option. ; ; This utility gets its input via .CSISPC and .GTLIN commands, and therefore ; can be run from Indirect Command Files. (Actually this was the original ; intent. I needed a method of verifying disks prior to executing indirect ; commands that resulted in the destruction of data/programs. The Severe ; Error exit stops any .COM process [except if SET ERROR NONE is currently ; in effect].) Like other system utilities, when activated from indirect ; command files, if there is no input-line currently available in the body ; of the indirect command file (i.e. the "^C" option) one will be collected ; from the console terminal. ; ; Examples: *RK3:/V/O ! Verifies that RK3: has ; Volume ID ? >DEVELOPMENT ! Volume ID "DEVELOPMENT " ; Owner ? >LARRY ! and Owner "LARRY " ; Volume ID = "DEVELOPMENT " ! and displays the values ; Owner = "LARRY " ! set for device RK3: ; ; *DL1:/V ! Verifies that DL1: has ; Volume ID ? >SYSTEM DISK ! Volume ID "SYSTEM DISK " ; Owner ? >O.C.S. - 005 ! and Owner "O.C.S. - 005" ; Volume ID = "SYSTEM DISK " ! and displays the values ; Owner = "O.C.S. - 005" ! set for device DL1: ; ; */O/Q ! Verifies that DK: has ; Owner ? >LARRY ! OWNER "LARRY " ; ; *.NEW= ! Generates warning message ; VFY-W-Output Specification Ignored ! about illegal output spec ; Volume ID = "DEVELOPMENT " ! and displays the values ; Owner = "LARRY " ! set for device DK: ; ; */Q ! No verification nor display ; .PAGE .SBTTL MACRO AND SYMBOLIC DEFINITIONS ; ; System MACRO definitions ; .MCALL .GTLIN,.PRINT,.TTYOUT,.CSISPC,.DSTATUS,.FETCH .MCALL .QSET,.LOOKUP,.READW,.CLOSE,.SRESET,.SETTOP,.EXIT ; ; Local MACRO definitions ; SOBINS = 0 ; Comment-out for CPUs without SOB instruction ; .IF NDF SOBINS .MACRO SOB REG, ADR DEC REG BNE ADR .ENDM .ENDC ; ; Local symbolic definitions ; A.JSW = 44 ; ADDRESS OF JOB STATUS WORD A.HIAD = 50 ; ADDRESS OF OUR HIGHEST ADDR A.SYER = 52 ; ADDRESS OF SYSTEM ERROR STAT A.USER = 53 ; ADDRESS OF USER ERROR STATUS B.IND = 10 ; BIT FOR NON-TERM. .GTLIN B.TTLC = 40000 ; BIT FOR LOWERCASE TTY INPUT B.SUCC = 1 ; BIT FOR SUCCESS STATUS B.EROR = 4 ; BIT FOR ERROR STATUS B.REEN = 20000 ; BIT FOR REENTER STATUS B.SEVR = 10 ; BIT FOR SEVERE ERROR STATUS B.DEVT = 100000 ; BIT FOR .DSTATUS DEVICE-TYPE B.FLG1 = 10 ; BIT FOR FLAG #1, "/V" FOUND B.FLG2 = 20 ; BIT FOR FLAG #2, "/O" FOUND B.FLG3 = 40 ; BIT FOR FLAG #3, "/Q" FOUND B.FLG4 = 100 ; BIT FOR FLAG #4, FATAL ERROR C.IN = 3 ; CHANNEL FOR INPUT L.BUFR = 256. ; LENGTH OF DISK I/O BUFFER L.QUEE = 10. ; LENGTH OF QUEUE ELEMENT L.OSPC = 5. ; LENGTH OF OUTPUT FILESPEC L.ISPC = 4. ; LENGTH OF INPUT FILESPEC L.EMTA = 5. ; LENGTH OF EMT ARGUMENT BLOCK L.VALU = 12. ; LENGTH OF VERIFICATION VALUE N.QUEE = 1. ; NUMBER OF NEW QUEUE ELEMENTS N.OSPC = 3. ; NUMBER OF OUTPUT FILESPEC(S) N.ISPC = 6. ; NUMBER OF INPUT FILESPEC(S) O.VID = 730 ; OFFSET TO VOLUME_ID O.OWN = 744 ; OFFSET TO OWNER NAME O.FN1 = 2 ; OFFSET TO FILENAME(1) O.FN2 = 4 ; OFFSET TO FILENAME(2) O.EXT = 6 ; OFFSET TO EXTENSION O.SIZ = 10 ; OFFSET TO SIZE VALUE O.DHSZ = 2 ; OFFSET TO DEV. HANDLER SIZE O.DHLA = 4 ; OFFSET TO HANDLER LOAD ADDR BLCK = 1 ; BLOCK # TO READ FROM DISK SPACE = 040 ; ASCII " " OOH = 117 ; ASCII "O" QUE = 121 ; ASCII "Q" VEE = 126 ; ASCII "V" ; .PAGE .SBTTL MAINLINE CODE ; ; Executable code starts here ; VFY:: NOP ; Place-holder for REEnter BIS #,@#A.JSW ; SET THE JSW BITS CLRB USRBUF ; SET-UP NULL STRING .CSISPC #CSITBL,#CSIEXT,#0,#USRBUF ; CALL THE COMMAND STRING INTR BCC 20$ ; CC = SUCCESS --> BRANCH 10$: .PRINT #CSIERR ; INFORM THE USER ABOUT ERROR JMP ERROR ; ...AND GO FINISH-UP ; ; Check for any output specifications ; 20$: MOV #OFILE,R2 ; R2 POINTS TO 1ST OUTPUT SPEC MOV #N.OSPC,R1 ; R1 HAS NUMBER OF SPECS 30$: TST (R2) ; ANYTHING FOUND ? BEQ 40$ ; EQ = NO --> BRANCH .PRINT #OUTERR ; WARN THE USER ABOUT IT 40$: ADD #,R2 ; BUMP POINTER TO NEXT ENTRY SOB R1,30$ ; LOOP TILL ALL CHECKED ; ; Check for an input device specification, if none load the default device ; 50$: MOV #IFILE,R2 ; R2 POINTS TO 1ST INPUT SPEC MOV #N.ISPC,R1 ; R1 HAS NUMBER OF SPECS 60$: TST (R2) ; ANYTHING FOUND ? BNE 70$ ; NE = YES --> BRANCH ADD #,R2 ; BUMP POINTER TO NEXT ENTRY SOB R1,60$ ; LOOP TILL ALL CHECKED MOV #IFILE,R5 ; R5 HOLDS INPUT SPEC ADDRESS MOV DEFDEV,(R5) ; ASSUME DEFAULT DEVICE (DK:) BR 120$ ; ...AND GO ZERO THE FILESPEC ; ; Found an input device specification, check for filename and multiples ; 70$: TST O.FN1(R2) ; 1ST HALF OF FILENAME FOUND ? BNE 80$ ; NE = YES --> BRANCH TST O.FN2(R2) ; 2ND HALF OF FILENAME FOUND ? BNE 80$ ; NE = YES --> BRANCH TST O.EXT(R2) ; EXTENSION FOUND ? BEQ 90$ ; EQ = NO --> BRANCH 80$: .PRINT #FILERR ; WARN THE USER ABOUT IT 90$: MOV R2,R5 ; R5 HOLDS INPUT SPEC ADDRESS DEC R1 ; COUNT THAT ONE AS CHECKED 100$: ADD #,R2 ; BUMP POINTER TO NEXT SPEC TST (R2) ; ANYTHING FOUND ? BEQ 110$ ; EQ = NO --> BRANCH .PRINT #MDVERR ; TELL USER ABOUT ERROR BR 120$ ; ...AND PROCEED 110$: SOB R1,100$ ; LOOP TILL ALL CHECKED ; ; Insure that the input specification has no filename or extension ; at this point R5 points to the device specification ; 120$: CLR O.FN1(R5) ; ZERO 1ST HALF OF FILENAME CLR O.FN2(R5) ; ZERO 2ND HALF OF FILENAME CLR O.EXT(R5) ; ZERO EXTENSION ; ; Check the stack for option (switch) information ; MOV #FLAGS,R4 ; R4 POINTS TO LOCAL FLAGS CLR (R4) ; CLEAR ALL FLAGS MOV (SP)+,R1 ; R1 HAS # SWITCHES SPECIFIED BEQ 190$ ; EQ = NONE --> BRANCH 130$: CMPB (SP),#VEE ; IS THIS SWITCH A "V" ? BNE 140$ ; NE = NO --> BRANCH BIS #B.FLG1,(R4) ; FLAG "/V" FOUND BR 170$ ; ...AND CONTINUE CHECKING 140$: CMPB (SP),#OOH ; IS THIS SWITCH AN "O" ? BNE 150$ ; NE = NO --> BRANCH BIS #B.FLG2,(R4) ; FLAG "/O" FOUND BR 170$ ; ...AND CONTINUE CHECKING 150$: CMPB (SP),#QUE ; IS THIS SWITCH A "Q" ? BNE 160$ ; NE = NO --> ERROR BIS #B.FLG3,(R4) ; FLAG "/Q" FOUND BR 170$ ; ...AND CONTINUE CHECKING 160$: MOVB (SP),ILLSW ; LOAD ILLEGAL SWITCH INTO MSG .PRINT #OPTERR ; WARN USER ABOUT BAD SWITCH 170$: TST (SP)+ ; DOES A VALUE WORD FOLLOW ? BPL 180$ ; PL = NO --> BRANCH TST (SP)+ ; IGNORE IT 180$: SOB R1,130$ ; LOOP TILL ALL OPTIONS DONE ; ; If the user specified verification, then get the values to be used ; at this point R4 points to the option flag word ; 190$: BIT #B.FLG1,(R4) ; VERIFY VOLUME_ID ? BEQ 200$ ; EQ = NO --> BRANCH MOV #VOLID,R1 ; R1 POINTS TO STORAGE BUFFER MOV #VOLPRM,R2 ; R2 POINTS TO PROMPT MESSAGE JSR PC,GETVAL ; GET THE VALUE FROM THE USER BCC 200$ ; CC = SUCCESS --> BRANCH .PRINT #VLUERR ; WARN USER ABOUT THE ERROR BR 190$ ; ...AND DO IT AGAIN 200$: BIT #B.FLG2,(R4) ; VERIFY OWNER ? BEQ 210$ ; EQ = NO --> BRANCH MOV #OWNER,R1 ; R1 POINTS TO STORAGE BUFFER MOV #OWNPRM,R2 ; R2 POINTS TO PROMPT MESSAGE JSR PC,GETVAL ; GET THE VALUE FROM THE USER BCC 210$ ; CC = SUCCESS --> BRANCH .PRINT #VLUERR ; WARN USER ABOUT THE ERROR BR 200$ ; ...AND DO IT AGAIN ; ; Check for random access device, load handler if needed, and open a channel ; 210$: MOV #ARGBLK,R1 ; R1 POINTS TO ARGUMENT BLOCK .DSTATUS R1,R5 ; GET STATUS OF INPUT DEVICE BCC 230$ ; CC = SUCCESS --> BRANCH 220$: .PRINT #DEVERR ; TELL USER ABOUT ERROR JMP ERROR ; ...AND GO FINISH-UP 230$: BIT #B.DEVT,(R1) ; IS IT A RANDOM-ACCESS DEV ? BEQ 220$ ; EQ = NO --> ERROR TST O.DHLA(R1) ; IS THE HANDLER AVAILABLE ? BNE 250$ ; NE = YES --> BRANCH MOV O.DHSZ(R1),R1 ; R1 HAS HANDLER'S SIZE MOV @#A.HIAD,R2 ; R2 HAS OUR CURRENT TOP ADDR ADD R2,R1 ; R1 GETS OUR NEW TOP ADDR .SETTOP R1 ; REQUEST IT FROM RMON SUB R2,R0 ; R0 HAS # OF BYTES ALLOCATED MOV R0,MEMEXT ; STORE IT CMP @#A.HIAD,R1 ; DID WE GET ALL OF IT ? BEQ 240$ ; EQ = YES --> BRANCH .PRINT #MEMERR ; TELL USER ABOUT ERROR JMP ERROR ; ...AND GO FINISH-UP 240$: ADD #2,R2 ; R2 POINTS TO EXTENDED AREA .FETCH R2,R5 ; FETCH THE DEVICE HANDLER BCC 250$ ; CC = SUCCESS --> BRANCH .PRINT #DHNERR ; TELL USER ABOUT ERROR JMP ERROR ; ...AND GO FINISH-UP 250$: .LOOKUP #ARGBLK,#C.IN,R5,#0 ; DO A NON-DIRECTORY OPEN BCC 270$ ; CC = SUCCESS --> BRANCH 260$: .PRINT #INTERR ; TELL USER ABOUT FATAL ERROR BIS #B.FLG4,(R4) ; FLAG FATAL ERROR JMP ERROR ; ...AND GO FINISH-UP ; ; Here is where we read the information from the input device ; 270$: .QSET #QUEUE,#N.QUEE ; ALLOCATE MORE QUEUE ELEMENTS MOV #DSKBUF,R3 ; R3 POINTS TO I/O DATA BUFFER .READW #ARGBLK,#C.IN,R3,#L.BUFR,#BLCK ; READ DATA FROM DEVICE BCC 280$ ; CC = SUCCESS --> BRANCH CMPB @#A.SYER,#1 ; HARD ERROR ? BNE 260$ ; NE = NO --> FATAL ERROR .PRINT #HIOERR ; TELL USER ABOUT ERROR JMP ERROR ; ...AND GO FINISH-UP 280$: .CLOSE #C.IN ; CLOSE THE CHANNEL ; ; This is where we display the data read, unless the user specified quiet ; BIT #B.FLG3,(R4) ; ARE WE IN QUIET MODE ? BNE 290$ ; NE = YES --> BRANCH .PRINT # ; OUTPUT A PAIR MOV R3,R1 ; R1 POINTS TO DATA BUFFER ADD #O.VID,R1 ; OFFSET TO VOLUME_ID DATA .PRINT #VOLMSG ; DISPLAY THE VOLUME_ID JSR PC,PUTVAL ; ...DATA FROM THE DEVICE .PRINT #MSGEND ; ...ON THE CONSOLE MOV R3,R1 ; R1 POINTS TO DATA BUFFER ADD #O.OWN,R1 ; OFFSET TO OWNER NAME DATA .PRINT #OWNMSG ; DISPLAY THE OWNER NAME JSR PC,PUTVAL ; ...DATA FROM THE DEVICE .PRINT #MSGEND ; ...ON THE CONSOLE ; ; This is where we do the verification(s), unless the user didn't specify ; 290$: BIT #B.FLG1,(R4) ; VOLUME_ID VERIFICATION ? BEQ 300$ ; EQ = NO --> BRANCH MOV #DSKBUF,R0 ; R0 POINTS TO DATA BUFFER ADD #O.VID,R0 ; OFFSET TO VOLUME_ID DATA MOV #VOLID,R1 ; R1 POINTS TO USER'S VALUE JSR PC,COMPAR ; GO DO THE COMPARISON BCC 300$ ; CC = MATCH --> BRANCH .PRINT #VIVERR ; TELL USER ABOUT FAILURE BIS #B.FLG4,(R4) ; FLAG FATAL ERROR 300$: BIT #B.FLG2,(R4) ; OWNER NAME VERIFICATION ? BEQ DONE ; EQ = NO --> BRANCH MOV #DSKBUF,R0 ; R0 POINTS TO DATA BUFFER ADD #O.OWN,R0 ; OFFSET TO OWNER NAME DATA MOV #OWNER,R1 ; R1 POINTS TO USER'S VALUE JSR PC,COMPAR ; GO DO THE COMPARISON BCC DONE ; CC = MATCH --> BRANCH .PRINT #OWVERR ; TELL USER ABOUT FAILURE BIS #B.FLG4,(R4) ; FLAG FATAL ERROR BR DONE ; ...AND FINISH-UP ; DONE: BIT #B.FLG4,(R4) ; FATAL ERROR OCCURED ? BNE ERROR ; NE = YES --> BRANCH .SRESET ; DO A SOFTWARE RESET MOV @#A.HIAD,R1 ; R1 HAS OUR CURRENT TOP ADDR SUB MEMEXT,R1 ; R1 GETS OUR OLD TOP ADDR .SETTOP R1 ; RESET OURSELVES BISB #B.SUCC,@#A.USER ; FLAG SUCCESS FOR RMON BIS #B.REEN,@#A.JSW ; Flag REEnter OK for KMON BR KMON ; ...AND EXIT TO KMON ERROR: CLR R0 ; FLAG IMPLICIT .HRESET BISB #B.EROR,@#A.USER ; FLAG ERROR FOR RMON BIT #B.FLG4,(R4) ; FATAL ERROR CONDITION ? BEQ KMON ; EQ = NO --> BRANCH BISB #B.SEVR,@#A.USER ; FLAG SEVERE ERROR FOR RMON KMON: .EXIT ; EXIT TO KMON ; .PAGE .SBTTL SUBROUTINES ; GETVAL: MOV #USRBUF,R3 ; R3 POINTS TO USER'S BUFFER .GTLIN R3,R2 ; GET INPUT FROM THE USER MOV #L.VALU,R0 ; R0 HAS MAX CHARACTERS ADD R3,R0 ; R0 HAS MAX ADDR FOR TERM 10$: MOVB (R3)+,(R1)+ ; TRANSFER A CHARACTER BEQ 20$ ; EQ = TERMINATOR --> BRANCH CMP R3,R0 ; TOO MANY FOUND ? BLOS 10$ ; LOS = NO --> BRANCH SEC ; FLAG ERROR STATUS RTS PC ; ...AND RETURN TO THE CALLER 20$: DEC R1 ; ADJUST THE "PUT" POINTER SUB R3,R0 ; COMPUTE NUMBER OF CHARACTERS INC R0 ; ...TO BE FILLED BEQ 40$ ; EQ = NONE --> BRANCH 30$: MOVB #SPACE,(R1)+ ; FILL-IN AN ASCII SPACE CHAR SOB R0,30$ ; LOOP TILL MAX CHARS ARE DONE 40$: CLRB (R1)+ ; INSERT TERMINATOR BYTE CLC ; FLAG SUCCESS STATUS RTS PC ; ...AND RETURN TO THE CALLER ; PUTVAL: MOV #L.VALU,R2 ; R2 HAS CHARACTER COUNT 10$: MOVB (R1)+,R0 ; LOAD A CHARACTER .TTYOUT ; PRINT IT SOB R2,10$ ; LOOP TILL ALL ARE OUTPUT RTS PC ; ...AND RETURN TO THE CALLER ; COMPAR: MOV #L.VALU,R2 ; R2 HAS CHARACTER COUNT 10$: CMPB (R0)+,(R1)+ ; DO THESE TWO MATCH ? BEQ 20$ ; EQ = YES --> BRANCH SEC ; FLAG ERROR STATUS RTS PC ; ...AND RETURN TO THE CALLER 20$: SOB R2,10$ ; LOOP TILL ALL CHECKED CLC ; FLAG SUCCESS STATUS RTS PC ; ...AND RETURN TO THE CALLER ; .PAGE .SBTTL DATA DEFINITIONS ; ; Local data definitions ; DSKBUF: .BLKW L.BUFR ; DISK DATA BUFFER USRBUF: .BLKB 82. ; USER'S INPUT BUFFER QUEUE: .BLKW ; NEW QUEUE ELEMENT LIST DEFDEV: .RAD50 \DK \ ; DEFAULT DEVICE SPEC CSIEXT: .RAD50 \ LSTLSTLST\ ; DEFAULT EXTENSIONS FOR CSI CSITBL: ; CSI COMMAND TABLE OFILE: .BLKW ; OUTPUT FILESPEC(S) IFILE: .BLKW ; INPUT FILESPEC(S) ARGBLK: .BLKW L.EMTA ; EMT ARGUMENT BLOCK MEMEXT: .WORD 0 ; MEMORY EXTENSION SIZE VOLID: .BLKB ; VOLUME_ID BUFFER OWNER: .BLKB ; OWNER BUFFER FLAGS: .WORD 0 ; LOCAL FLAGS .NLIST BEX OUTERR: .ASCIZ <15>\VFY-W-Output Specification Ignored\ FILERR: .ASCIZ <15>\VFY-W-Filename Specification Ignored\ MDVERR: .ASCIZ <15>\VFY-W-Multiple Device Specification Ignored\ OPTERR: .ASCII <15>\VFY-W-Option "/\ ILLSW: .ASCIZ \X" Ignored\ VLUERR: .ASCIZ <15>\VFY-W-Verification Value Too Long\ CSIERR: .ASCIZ <7><15>\VFY-E-Invalid CSI Command\ DEVERR: .ASCIZ <7><15>\VFY-E-Invalid Device Specification\ DHNERR: .ASCIZ <7><15>\VFY-E-Device Handler Not Found\ MEMERR: .ASCIZ <7><15>\VFY-E-Insufficient Memory for Device Handler\ HIOERR: .ASCIZ <7><15>\VFY-E-Hard Error on Input Device\ VIVERR: .ASCIZ <7><15>\VFY-F-Volume ID Verification Error !\ OWVERR: .ASCIZ <7><15>\VFY-F-Owner Verification Error !\ INTERR: .ASCIZ <7><15>\VFY-F-Internal Error !\<7> VOLPRM: .ASCII <15>\Volume ID ? >\<200> OWNPRM: .ASCII <15>\Owner ? >\<200> VOLMSG: .ASCII <15>\Volume ID = "\<200> OWNMSG: .ASCII <15>\Owner = "\<200> MSGEND: .ASCIZ \"\ .EVEN ; .END ; REEnter w/b @ VFY