.MCALL .MODULE .MODULE BUPCMD,Version=15,Ident=NO,Comment= ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. .SBTTL Edit History ; 23-Jun-89 RHH V5.5 Work ; 17-Jan-91 WFG Fix DEVCHK to allow output to NL: as well as TT: .SBTTL RT-11 Macros .MCALL .ASSUME .BR .CLOSE .CSTAT .DSTAT .ENTER .GTLIN .MCALL .GVAL .HERR .LOOKUP .PRINT .PURGE .QSET .READW .MCALL .SERR .SETTOP .SRESET .WRITW .SBTTL Local Macros .MACRO ...... .ENDM .SBTTL Equates BEEP =: 7 ; BELL character TRUE =: 200 ; Option selected flag value ; Bits defined for the SEQPOS word -- device characteristics FR.DEV =: 1 ; Foreign Random Device TP.DEV =: 200 ; Tape Device FR.OUT =: FR.DEV ; Foreign Random Output device TP.OUT =: TP.DEV ; Tape Output Device FR.IN =: FR.DEV*400 ; Foreign Random Input device TP.IN =: TP.DEV*400 ; Tape Input Device .SBTTL Local Data .PSECT CMDDAT,D .NLIST BEX ODTYPE: .WORD 0 ; Home block's BUP ID code SYCHK: .WORD 0 ; Temp storage for SY name DEFEX: .WORD 0 ; dynamic default extention SYDN: .RAD50 /SY / ; system device name ODEFS: DSKEX: .RAD50 /DSK/ ; output default extentions DIREX: .RAD50 /DIR/ ; (preserve BUPEX: .RAD50 /BUP/ ; this order) NSY1:: .ASCII /Restoring over SYSTEM volume!/<0> NSY2:: .ASCII \ :/Restore device; Are you sure? \<200> SEQDEV: .BYTE 0 .EVEN .PSECT CMDCOD,I .LIST BEX .SBTTL GETHDR - Calculate memory available ;+ ; The first free location above the program is found and saved for ; loading the first handler (or temporary buffer space). The address ; below the base of the usr is found and a settop is issued to this ; address. This address is declared as the top address of the program. ; This routine is executed only once in a backup session, once the ; calculations are performed the values stay fixed. ; ; MEMORY LAYOUT ; ; | | ; | USR | ; ----------------- ; | | TOPADD ; | | ; | | ; | | ; | | ; | | ; | | HDRADD ; ----------------- ; | CODE | ; | | ; | | ;- .ENABL LSB GETHDR::MOV @#$USRTO,HDRADD ; Get address of high limit ADD #2,HDRADD ; Point to first free location .SETTOP #177776 ; Get all possible memory MOV R0,TOPADD ; Save the top address CMDOVR::RETURN ; Load command-code overlay ...... .DSABL LSB .SBTTL FILCHK - Check/retrieve filespecs ;+ ; The command lines accepted by backup are a subset of the accepted ; lines by CSI, therfore the command line must be parsed. ; The command line and the rules by backup are: ; ; A. */OPTION ; B. *FILESPEC=FILESPEC[,/OPTION] OR *=FILESPEC[/OPTION] ; C. *=/OPTION ; ; o input and output device must be different ; o default device DK is accepted ; ; Two flags are used to determine missing filenames or filespecs ; so later on depending on the option entered we can determine if ; the command line is valid. These flags are NONAME and NOUTFL. ; Pointers to the filespec buffer (RAD50) and the (ASCII) command ; line are maintained and used to call the routines which determine ; that no more files where entered, and that the device is valid. ; ; FSPEC = Address where CSI stored the RAD50 equivalent of ; the command filespecs ; ; FSASC = Address where the ASCII command line was stored ; ; CALL FILCHK ; .ENABL LSB FILCHK::MOV #ODEFS,R0 ; Point to default extensions TSTB GIV.R ; /SUBSET specified? BMI 10$ ; use .DSK if so. .ASSUME BUPEX EQ ODEFS+4 CMP (R0)+,(R0)+ ; otherwise, use .BUP 10$: MOV @R0,DEFNAM+4 ; Setup default saveset extention 20$: MOV #FSPEC,R0 ; Point to output device zero MOV R0,R2 ; Save for later TST (R0)+ ; Output device? BNE 50$ ; Yes, branch ; No primary output was specified. Check for listing device in ; third position (V5.5) ADD #<2*OUSPSZ>,R2 ; Point to 3rd output spec TST @R2 ; was one supplied? BEQ 40$ ; branch if not. TST -(R0) ; back up to 1st output spec MOV #5,R4 ; move 5-word entry... 30$: MOV @R2,(R0)+ ; move 3rd to 1st CLR (R2)+ ; and clear the 3rd DEC R4 BNE 30$ MOVB #TRUE,GIV.L ; Set the LISTING flag BR 20$ ; and go around again. ...... ; Definitely NO output spec... *[=]inp:[filnam][/options]. SAVEOP ; inserted an asterisk for filnam if none was supplied. Remove it now ; so that "*dev:/S/L doesn't trip on input saveset wildcards. 40$: BISB #TRUE,NOUTFL ; Set no output file flag BISB #TRUE,NONAME ; Check for no more output specs MOV #FSPEC,R0 MOV R0,R4 ADD #OUSPSZ,R0 ; R0--> NEXT OUTPUT spec ADD #INSPST,R4 ; R4--> FIRST INPUT spec CALL NOMORE ; Check no more output specs MOV R4,R2 ; Save pointer for later ; No OUTPUT; Check for presence of input spec TST (R2)+ ; Is there an INPUT device spec? BEQ 60$ ; If not, error. ; No OUTPUT; Command is of form "[=]inp:[xxx]/x" CMP @R2,#ASTERK ; Is filename SAVEOP's asterisk? BNE 42$ CLR @R2 ; Clobber SAVEOP's asterisk in input 42$: TSTB GIV.Z ; INITIALIZE? BPL 100$ ; branch if not. TST @R2 ; Yes. Filespec present? BEQ 100$ ; No. That's good. BR 60$ ; Filename... That's bad. ...... ; OUTPUT was specified. Command is of form "out:[xxx]=?" 50$: MOV @R2,OUTDEV ; Save output device TST @R0 ; Output filename? BNE 70$ ; Yes, branch 60$: JMP INVCMD ; <-F-Invalid command> ...... ; Command is of form "out:xxx=?" Check for a name in output spec. 70$: MOV #3,R2 ; Check 2 name words and extension 72$: CMP #ASTERK,@R0 ; Is it an asterisk? BEQ 74$ ; If so, keep checking CMP @R0,#-1 ; or default extension? BEQ 74$ ; that's ok for noname TST @R0 ; or blanks? BNE 80$ ; No. There's a name in here. 74$: TST (R0)+ ; advance to next word DEC R2 BGT 72$ ; check all three words 76$: BISB #TRUE,NONAME ; Indicate NO OUTPUT FILENAME ; Determine appropriate default extension for output 80$: MOV #FSPEC+6,R0 ; Point to output spec extension CMP @R0,#-1 ; output filetype given? BNE 100$ ; Branch if it was. MOV #ODEFS,R2 ; Point to list of defaults TSTB GIV.R ; /SUBSET given? BMI 90$ ; Branch if so .ASSUME DIREX EQ DSKEX+2 TST (R2)+ ; advance to ".DIR" TSTB GIV.L ; /LIST given? BMI 90$ ; Branch if so .ASSUME BUPEX EQ DIREX+2 TST (R2)+ ; advance to ".BUP" 90$: MOV @R2,@R0 ; Store a real default extension. ; Check for extra output specs 100$: MOV #FSPEC,R0 ; Point to output spec MOV R0,R4 ADD #OUSPSZ,R0 ; End of comparison ADD #INSPST,R4 ; Pointer to end of output spec CALL NOMORE ; Check for no more output specs MOV R4,R0 ; Save pointer to begin of input TST (R4)+ ; Input device? BNE 120$ ; Yes. branch. ; Command has NO input specs MOV #FSPEC,R4 TSTB GIV.Z ; is this a KMON INIT/BACKUP? BPL 110$ ; branch if not. MOV (R4)+,(R0)+ ; let INP dev = specified OUT dev. MOV (R4)+,(R0)+ ; and illegal filspc, if any, BR 40$ ; go around again. ...... 110$: ADD #SPCSIZ,R4 ; End of compare CALL NOMORE ; Check nomore entries BIS #BIT15,NOUTFL ; Indicate no input device BIS #BIT15,NONAME ; Flag no input filename RETURN ...... ; Command has an input spec 120$: MOV @R0,INPDEV ; Save input device TST @R4 ; Input filename? BEQ 130$ ; No, branch CMP #ASTERK,@R4 ; Asterisk? BNE 140$ ; No. branch. ; Command has input device, but no file spec 130$: BIS #BIT15,NONAME ; Flag no input filename ; Command has an input spec-- ; Depending on the operation type (BACKUP, RESTORE (/X) or LIST (/L)), ; assign appropriate default filetypes to the input specs. 140$: MOV R0,-(SP) CALL STOSPE ; Convert specs to ASCII MOV (SP)+,R0 MOV #ASTERK,R2 ; normally, use ".*" TSTB GIV.L ; was /L specified? BMI 170$ ; branch if so TSTB GIV.X ; /RESTORE? BPL 150$ TSTB GIV.F ; /RESTORE/FILE? BPL 150$ TSTB GIV.I ; Not /DEVICE? BPL 160$ ; /X/F -> use .BUP default extention 150$: TSTB GIV.S ; /SAVESET specified? BMI 170$ ; if so, it will be taken care of. TSTB GIV.I ; /DEVICE? BPL 170$ ; Use .* if not TSTB GIV.F ; /DEVICE/FILE? BMI 170$ ; Use .* if so ; Option combination is /RESTORE/FILE or /DEVICE, possibly without /SAVESET ; or /SUBSET. Check for invalid impure wildcards, and then use .BUP as the ; default input extension. 160$: MOV BUPEX,R2 ; Default to .BUP for /DEVICE saveset CALL NOWILI ; Store the default extension for input. 170$: MOV R2,DEFEX ; save good default extension .BR INPLST ; Build ASCII input spec list .DSABL LSB .SBTTL INPLST - Build input spec list ; Build ASCII filespec string from all non-/S input specs ; On entry, R0 points to the first input device specification in ; the FSPEC list. .ENABL LSB INPLST: MOV #3,R3 ; start with file 3 (1st input spec) MOV #ASCLST,R1 ; point to ASCII file list area CLRB NISPEC ; reset input spec count 10$: MOV (R0)+,R2 ; null device spec? BEQ 150$ CMP R2,DKDEV ; DK: specified (by KMON)? BEQ 20$ ; if so, let that through. CMP R2,INPDEV ; same device? BEQ 20$ ; if not, error JMP INVDCM ; ?BUP-F-Invalid device combination ...... 20$: MOVB GIV.X,R2 ; If not /RESTORE BISB GIV.L,R2 ; or /LIST BEQ 110$ ; then ignore /SAVESET's filespec CMPB R3,SSSPEC+1 ; is this the /SAVESET file? BNE 110$ ; if not, branch. ; This is the input spec with /S attached. Save it as the input device. MOV #INFIL,R2 ; if /S, save it in special place MOV INPDEV,(R2)+ ; do the device name, ; Check for wildcards (invalid in input saveset names) 30$: CALL NOWILI ; Check for invalid wildcards ; If no extension was specified, tack one on now. TST NONAME ; primary input filename supplied? BPL 70$ ; branch if so. MOV DEFNAM,(R2)+ ; otherwise, use "BACKUP" MOV DEFNAM+2,(R2)+ ADD #4,R0 BR 80$ 70$: MOV (R0)+,(R2)+ ; then the saveset name MOV (R0)+,(R2)+ 80$: CMP @R0,#-1 ; extension not specified? BNE 100$ ; if specified, branch. TSTB GIV.R ; /SUBSET logical disk input? BPL 90$ MOV DSKEX,@R0 ; if so, use .DSK for input BR 100$ 90$: MOV BUPEX,@R0 ; if not specified, use ".BUP" 100$: MOV (R0)+,(R2)+ ; copy the extension BR 170$ ; continue without moving R0 ...... ; Process an input spec. Convert RAD50 to ASCII, insert dots, commas ; etc., to make compatible with IGTDIR. 110$: TST @R0 ; null filespec? BEQ 160$ ; skip it if so INCB NISPEC ; Add one to input spec count CMP R1,#ASCLST ; first entry to convert? BEQ 120$ ; if so, omit the COMMA. MOVB #',,(R1)+ ; insert a COMMA in the ASCLST area BR 130$ 120$: CLRB WILDFG ; Assume no wildcards 130$: MOV R0,R2 ; let R2 -> RAD50 (R1 points to ASCII) MOV R1,R4 ; save copy of string pointer MOV #2,R5 ; do 2 words worth of name CALL SELECT ; convert RAD50 name to ASCII CALL SQBLNK ; squeeze out trailing blanks MOVB #'.,(R1)+ ; insert a DOT CMP (R2)+,(R2)+ ; point to RAD50 ext CMP @R2,#-1 ; extension not specified? BNE 140$ MOV DEFEX,@R2 ; replace -1 with a good default. 140$: MOV R1,R4 ; save copy of string pointer MOV #1,R5 ; do 1 word of extention CALL SELECT ; convert RAD50 ext to ASCII CALL SQBLNK ; squeeze out trailing blanks BR 160$ 150$: TST (R0)+ ; point to filename part 160$: ADD #,R0 ; point to next RAD50 spec 170$: INC R3 ; count specs CMP R3,#8. ; all done? BLE 10$ ; branch if not. CLRB @R1 ; plant a NULL at end of ASCLST ; .PRINT #ASCLST ; uncomment to see what IGTDIR gets RETURN ...... .DSABL LSB .SBTTL SQBLNK - Squeeze blanks and translate field ; This subroutine serves the code above in the following ways: ; ; 1. It backs up ASCII string pointer R1 to the character of a filename ; or filetype just beyond the last non-blank character in the field, ; ; 2. it re-translates dots and slashes (produced by R50ASC) to their ; original form, percents and asterisks. ; ; 3. If a wildcard filespec is sensed, the variable WILDFG is set TRUE. ; ; On entry, R1 points beyond the result of a R50ASC conversion, ; and R4 should point to the first character of that destination ; string. .ENABL LSB SQBLNK: CMPB -1(R1),#40 ; previous char blank? BNE 10$ ; if not, continue. DEC R1 ; if yes, back up and try again. BR SQBLNK 10$: CMPB @R4,#'. ; Dot needs translation to '%'? BNE 20$ MOVB #'%,@R4 20$: CMPB @R4,#'/ ; Slash needs translation to '*'? BNE 30$ MOVB #'*,@R4 30$: CMPB @R4,#'* ; '*' wildcard? BEQ 40$ ; branch if so CMPB @R4,#'% ; '%' wildcard? BNE 50$ 40$: INCB WILDFG ; declare "wildcard!" 50$: INC R4 ; point to next character CMP R4,R1 ; any more to check? BLO 10$ ; branch up if so. RETURN ...... .DSABL LSB .SBTTL MAKDIR - Make a file container (description) ;+ ; Make a pseudo-disk container with ; ; o Boot block ; o Home block ; o blocks 2-5 ; o directory, starting at block 6 ; ; Store the pseudo-disk container as a temporary file on SY: ; ; Return a number of blocks required. ; ; Use SYSLIB routines IGTDIR and IGTENT to process the input device ; directory. ; ; 1. Open input device with IGTDIR ; ; 2. Get next matching entry with IGTENT ; ; 3. If none available, ; If no. of files > 0 ; flush current dir segment ; close file ; return n ; Else, ; purge file ; return -1 ; ; 4. If output not already open, ; open temporary file ; Make boot block ; Make home block ; Zero the in-between blocks ; Initialize directory segment ; ; 5. If directory segment is full, ; terminate it ; update the header to CURRENT segment ; flush it to output ; update the header to PREVIOUS segments ; initialize next directory segment ; ; 6. Store entry in current directory segment ; ; 7. Go to 2 ;- .PSECT .DATA.,D IMP1 = . NUMFSG: .WORD 0 ; No. files this segment NUMFLS: .WORD 0 ; No. of files all segments NUMSGS: .WORD 0 ; No. of segments STBLOK: .WORD 0 ; Starting data block for segment ENTSRC: .WORD 0 ; Pointer to dir entry buffer UNUSD: .WORD E.MPTY ; directory entry model .RAD50 / EMPTYFIL/ .WORD 0 ; length=0 .WORD 0 ; chan/jnum = 0 .WORD 0 ; date = 0 FINAL: .BYTE 0 ; Final segment flag EMPTNT: .BYTE 0 ; entry flag .EVEN IMP2 = . IMPSIZ = </2> ; size of above area .SBTTL MAKDIR - The code ;+ ; Build an RT-11-like container, containing a boot block, home block, ; secondary boot blocks, and directory blocks, based on files that ; match the supplied wildcard string. Store these blocks in a ; temporary file (WF:BUPTMP.TMP) for later use. ;- .PSECT .CODE.,I .ENABL LSB MAKDIR:: MOV INFIL,DEVSPC ; Make NFS dblk from input device MOV NHDRAD,R1 ; next available address CALL FETHAN ; Fetch input handler MOV R0,NHDRAD ; save next handler address MOV R0,IGDBLK+4 ; use this as IGTDIR work area MOV R0,IGEBLK+2 ; and as IGTENT work area ADD #,R0 MOV R0,IGDBUF ; use this as IGT dir buffer, ADD #2000,R0 ; (2 blocks worth) MOV R0,BUFADD ; Use buffer directly above handler ADD #2000,R0 ; (2 blocks worth) CMP R0,TOPADD ; Got enough memory for this? BLOS 10$ ; Branch if so. MOV #MEM,R1 ; Otherwise, terminate. JMP FATAL ; take fatal exit. ...... 10$: CLRB TMPOPN ; output not yet open CLRB EMPTNT ; entry not done yet MOV #INCHAN,IGDCHN ; channel to use MOV #DIRENT,ENTSRC ; point to IGTENT's entry area .SERR .LOOKUP #EMTARE,INCHAN,#DEVSPC,#-1. ; Open input device NFS BCC 12$ ; Continue on success JMP 150$ ; or quit on error. 12$: .HERR TSTB GIV.P ; /EXCLUDE? BPL 15$ ; branch if not INC IG.DEV+4 ; set IGTDIR flag for RETURN_ALL 15$: MOV #IGTDIR,R0 ; *** Setup wildcard search *** MOV #IGDBLK,R5 CALL CALL$F ; Call IGTDIR to setup dir search TST R0 ; Look at IGTDIR's return status BGE 25$ ; Continue if no error... JMP DIOERR ; Otherwise, I/O error on input. 25$: TSTB EMPTNT ; Final out yet? BEQ 30$ ; apparently not. INCB FINAL ; Yes? declare FINAL UPDATE JMP 80$ ; update and leave. ...... 30$: MOV #IGTENT,R0 ; *** Get next directory entry *** MOV #IGEBLK,R5 CALL CALL$F ; Call IGTENT... TSTB GIV.P ; /EXCLUDE in effect? BPL 32$ ; No. treat normally. CMP R0,#E.NOMA ; /EXCLUDE. Successful NOMATCH? BEQ 40$ ; Yes. Backup the file. TST R0 BPL 30$ ; Non-matching entry. Ask again. BR 33$ ; No more entries. Finished. ...... 32$: TST R0 ; Look at return status BGE 40$ ; Branch if good entry found. 33$: TST NUMFLS ; Uh oh. Any files found? BNE 35$ ; Branch if yes. PURTM: .PURGE TMPCHA ; otherwise, undo temp file SEC ; Indicate NO FILES RETURN ; and return to caller. ...... 35$: MOV #UNUSD,ENTSRC ; point to entry INCB EMPTNT ; declare doing entry 40$: TSTB TMPOPN ; Output already open? BNE 75$ ; Proceed if so. 45$: .SERR .ENTER #EMTARE,TMPCHA,#TMPFIL,#<6+<31.*2>> ; Open temporary file BCS 65$ ; Branch on error .HERR ; Just for a moment, store the data we have so far in the temporary file. ; This is done because CREBHB calls another overlay, which destroys the ; local data. After returning from the overlay, read it back in, and ; then begin to use the temporary file for holding a file container. .WRITW #EMTARE,TMPCHA,#IMP1,#IMPSIZ,#2 ; Save the impure area BCS 60$ ; Branch on error CALL CREBHB ; Create BOOT and HOME blocks TST R0 ; Success? BNE 60$ ; Branch on error .READW #EMTARE,TMPCHA,#IMP1,#IMPSIZ,#2 ; Read it back BCC 48$ ; Continue on success. ; Error returns 60$: CALL PURTM ; Undo temp file 65$: .HERR MOV #WR1,R1 ; I/O error on temp file MOV #TMPFIL,R3 JMP FATAL3 ...... ; Clear a 256-word area, and write 4 secondary boot blocks (2-5) 48$: MOV BUFADD,R1 ; Point to buffer, MOV #256.,R3 ; Clear the block buffer MOV R1,R2 50$: CLR (R2)+ DEC R3 BGT 50$ MOV #2,R2 ; starting at block 2, 55$: .WRITW #EMTARE,TMPCHA,R1,#256.,R2 ; Write 2ndary boot blocks BCS 60$ ; Branch if no write error INC R2 ; Next block CMP R2,#6 ; Ready for block 6? BLO 55$ ; loop if not. ; Initialize 1st directory segment in blocks 6 and 7 MOV #1,(R1)+ ; Init 1st D.TOTA CLR (R1)+ ; Init 1st D.NEXT MOV #1,(R1)+ ; Init 1st D.HIGH CLR (R1)+ ; Init 1st D.EXTR MOV #8.,@R1 ; Init 1st D.STRT MOV (R1)+,STBLOK ; Store it in variable MOV R1,R2 ; Point to 1st dir entry INCB TMPOPN ; Set OPEN flag CLR NUMFSG ; Clear file counters CLR NUMFLS CLRB FINAL ; Begin in NON_FINAL mode MOV #1,NUMSGS ; Init no. of segments ; If the segment is now full, move it out and update the others 75$: CMP NUMFSG,#<<512.-5>/7> ; Max num files per seg exceeded? BLO 125$ ; Branch if not full yet INC NUMSGS ; Declare one more segment 80$: MOV #E.EOS,(R1)+ ; Put END_OF_SEGMENT code in dir MOV BUFADD,R2 ADD #2000,R2 85$: CMP R1,R2 ; Segment completely padded? BHI 90$ ; Branch if so. CLR (R1)+ ; Pad some more. BR 85$ 90$: MOV BUFADD,R1 ; re-point to beginning of buffer MOV NUMSGS,R2 ; Get number of segments MOV R2,D.TOTA(R1) ; Store no. segs in this seg hdr MOV R2,R4 ; Save for updating later TSTB FINAL ; Is this the final segment? BNE 95$ DEC R2 ; Account for INC NUMSGS 95$: ASL R2 ; Convert no. segs to offset ADD #4,R2 ; and to block number 100$: .WRITW #EMTARE,TMPCHA,R1,#512.,R2 ; write segment 105$: BCS 60$ ; Branch on error. MOV R2,CONBLK ; Save number of container blocks ADD #2,CONBLK ; Before initializing the new segment, update the old ones 110$: TST -(R2) ; Back up block number by 2 CMP R2,#6 ; Block # lower than 1st dir block? BLO 120$ ; Branch if no more to do. .READW #EMTARE,TMPCHA,R1,#256.,R2 ; Read prev segment header BCS 105$ ; Branch on error ; .ASSUME D.TOTA EQ 0 MOV NUMSGS,@R1 ; Update D.TOTA MOV @R1,D.HIGH(R1) ; Update D.HIGH ADD #2,D.STRT(R1) ; account for 2 more dir blocks MOV R4,D.NEXT(R1) ; Update NEXT_SEGMENT .WRITW #EMTARE,TMPCHA,R1,#256.,R2 ; Write back prev segment BCS 105$ ; Branch on error DEC R4 ; NEXT_SEGMENT value for prev segment BR 110$ ; Do until no more segs to update ...... 120$: TSTB FINAL ; Last segment done? BNE 140$ ; If so, finish up. CLR NUMFSG ; Reset FILES_IN_SEGMENT counter MOV NUMSGS,(R1) ; Init new dir header CLR D.NEXT(R1) ; Init new NEXT value ADD #2,STBLOK ; Account for 2 more dir blocks MOV STBLOK,D.STRT(R1) ; Init new STRT value ADD #D.LENG,R1 ; Point to 1st entry ; Store entry in current directory segment buffer 125$: MOV ENTSRC,R4 ; Point to IGTENT's entry array 130$: MOV #7,R3 ; count 7 words ADD E.LENG(R4),STBLOK ; Update file starting block 135$: MOV (R4)+,(R1)+ ; move it in. DEC R3 BGT 135$ INC NUMFSG ; Increment no. files this segment INC NUMFLS ; Increment no. files all segments JMP 25$ ; Go try for another entry. ...... 140$: MOV STBLOK,FILSIZ ; Save the saveset size. .PURGE INCHAN ; Purge IGT(DIR,ENT)'s channel CLC ; Clear carry - done. RETURN ...... ; Handle .LOOKUP errors from MAKDIR 150$: .PURGE INCHAN JMP DIOERR ; <-F-Directory I/O error > ...... .DSABL LSB .SBTTL DEVCHK - Device check ;+ ; ; Determine the nature of the input and output devices. Do .DSTATUS ; request on each device, determine physical device names. Detect ; when input and output are the same device. This is invalid unless ; /SUBSET (/R) is specified. ; ; Save a one-word (two-byte) flag that signifies a device as a MAG_TAPE ; or as a Foreign-random device (FILST$=1 SPECL$=1). ; ; SEQPOS: input device byte : output device byte ; +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ ; |ITP| | | | | | |IFR|OTP| | | | | | |OFR| ; +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ ; ^ ^ : ^ ^ ; | | | | ; Input is tape Input is Output is tape Output is ; Foreign Foreign ;- .ENABL LSB ; Test OUTPUT device DEVCHK::TSTB NOUTFL ; Output device? BMI 20$ ; No, branch MOV #OUTDEV,R1 ; Given output device spec MOV #OUTASC,R2 ; Destination ASCII name CALL GDVNAM ; Get device name info MOV @R5,DSTOUT ;*C* save DSTAT word of output BCC 10$ ; Branch if DSTAT returned no error BIT #RONLY$,@R5 ; Will this thing do output ? BNE 30$ ; No, branch 10$: MOVB @R5,DEV1 ; Save output device code MOVB SEQDEV,SEQPOS ; save output device characteristic ; Test INPUT device 20$: TST INPDEV ; Is there an input device? BEQ 50$ ; No, branch MOV #INPDEV,R1 MOV #INASC,R2 ; Destination ASCII name CALL GDVNAM ; Get device name info BCC 40$ ; Branch if no error 30$: MOV #DEV,R1 ; <-F-Invalid device > JMP FATALD ...... 40$: MOVB @R5,DEV2 ; Save input device code MOVB SEQDEV,SEQPOS+1 ; save device characteristics byte ; If OUTPUT and INPUT are the same, check unit numbers TSTB GIV.R ; /SUBSET given? BMI 50$ ; Make an exception if so. CMP INPDEV,OUTDEV ; Same units? BNE 50$ ; No, branch; ok JMP INVDCM ; <-F-Invalid device combination> ...... ; Get Device Name and Status ; R1 -> RAD50 given device spec ; R2 -> ASCII destination of physical device name ; Assume REALIN does not alter R1 ; On return, R5 contains the DSTAT word GDVNAM: MOV @R1,DEVSPC ; get device name CALL DSTAT ; get device status BCS 50$ ; no device? MOV R2,-(SP) ; swap R1 and R2 for SELECT CALL REALIN ; Get real device name MOV R1,R2 ; Address of RAD50 physical name MOV (SP)+,R1 ; Address to store ASCII MOV R5,-(SP) ; save pointer to DSTAT word MOV #1,R5 ; Number of words to convert CALL SELECT ; convert RAD50 to ASCII MOV (SP)+,R5 ; restore pointer to DSTAT word 50$: RETURN ...... .DSABL LSB .SBTTL DSTAT - Get device status ;+ ; GET DEVICE STATUS: ; The status of the device requested is obtained. If the device is not ; installed, an error message is issued. If the device is valid, it is ; further tested for sequential magtape device. Bit 7 of SEQDEV is set ; if so. ; ; DEVSPC -> DEVICE RAD50 ; ; CALL DSTAT ; ; On exit, R5 points to the DSTATUS block ; ; C=1 - DEVICE IS SEQUENTIAL BUT NOT MAGTAPE ; C=0 - VALID DEVICE ;- .ENABL LSB DSTAT: CLRB SEQDEV ; Assume not magtape .DSTAT #DEVBLK,#DEVSPC ; Get status BCC 10$ ; Branch if no error MOV #DEV,R1 ; <-F-Invalid device dev:> JMP FATALD ...... 10$: MOV #DEVBLK,R5 ; R5 -> device status block ; .ASSUME FILST$ LT 0 TST @R5 ; Sequential device? BMI 50$ ; No, branch BIT #SPECL$,@R5 ; Yes. SPECIAL_DIRECTORY? BEQ 30$ ; No? Not valid. BIT #WONLY$,@R5 ; is it WRITE_ONLY? BNE 20$ ; if so, it's probably for dir list. BISB #TP.DEV,SEQDEV ; Set magtape flag 20$: TST (PC)+ ; good return 30$: SEC ; bad return 40$: RETURN ...... ; The FILST$ bit is set, indicating that the device is random-access. ; If the device is a Foreign-Random device (file but no device access), ; signify it by setting the low bit. 50$: BIT #SPECL$,@R5 ; KP-style device? BEQ 20$ ; branch and return if not .ASSUME FR.DEV EQ 1 INCB SEQDEV ; flag it and return. BR 20$ ...... .DSABL LSB .SBTTL NOMORE - No more file entrys ;+ ; Check that no more file specifications exists between the range ; passed to the subroutine. ; ; R0---> points to start comparison data on csi buff ; R4---> address of where to end comparison on csi buff ; ; CALL NOMORE ; ; R0,R4 - MODIFIED ;- .ENABL LSB NOMORE:: TST (R0)+ ;Anything there BEQ 10$ JMP INVCMD ;Yes, error ...... 10$: CMP R0,R4 ;Are we finish BNE NOMORE ;No,repeat RETURN ;Return to caller ...... .DSABL LSB .SBTTL OPTCHK - Check options entered ;+ ; After determining the option entered, the appropriate ; routine is entered that will check that the command line follows ; the syntax for that option. In addition, the option flag will be ; set in this routine. ; ; ----------------------------------------------------------------- ; | | | | | | | | | | /F|/I | | | | | | ; | 1 | | |/L |/Z | |/R |/S | 1 | |/X |/X |IMA|/I |/A |TA | ; ----------------------------------------------------------------- ; 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ; ; BIT15 - IF SET INDICATES GROUP A COMMANDS A$GRP ; ; BIT7 - IF SET INDICATES GROUP B COMMNADS B$GRP ; ; CALL OPTCHK ; ; R1,R3 - MODIFIED ; ; FLAGS$ ; OPTCHK - set as indicated above for corresponding command ; ; There are THREE principal mutually exclusive operations that BUP ; performs: ; ; 1. BACKUP ; 2. RESTORE ; 3. LIST ; ; INITIALIZE is treated as a special case of BACKUP ; ; For the option entered, a routine will be called which will check ; that the command line follows the syntax for that option. ; In addition, appropriate OPTACT flag bits will be set. ;- .ENABL LSB OPTCHK::TSTB GIV.R ; Check switch combinations BPL 10$ ; that are independent of TSTB GIV.S ; the three basic modes BMI INVCM2 ; Cannot use /S and /R together 10$: TSTB GIV.L ; /L - LIST OPERATION? BPL 20$ CALLR CHKLOP ; Check /L - LIST ...... 20$: TSTB GIV.X ; /X - RESTORE OPERATION? BPL 30$ CALLR CHKXOP ; Check /X - RESTORE ...... ; If it's not LIST or RESTORE, then MUST be BACKUP (or INITIALIZE) 30$: .BR CHKBKO ; Check BACKUP (no option) .DSABL LSB .SBTTL CHKBKO - Backup check ;+ ; BACKUP CHECK - Check options on file backup operation. ; Check that there is both an input and output device. If /I ; is not supplied, there must be a filename specified on the ; input side. If the command involves a tape it must be on ; the output side. Finally set the mask. ;- .ENABL LSB CHKBKO: CLR R1 ; OPTACT bit accumulation ; Check for unquestionably bad option combinations... MOVB VONLY,R0 ; /VERIFY:ONLY? BISB GIV.O,R0 ; /ONLY:n? BMI INVCM2 ; Can't do that on BACKUP BIT #,SEQPOS ; Foreign Random input? BNE 25$ ; Can't do BIT #,SEQPOS ; Magtape operation? BEQ 20$ ; No, skip next ; It's a MAGTAPE operation... BIS #,R1 ; Set tape bit MOVB GIV.R,R0 ; /SUBSET specified? BISB GIV.G,R0 ; /NOSCAN specified? BMI INVOPD ; that's not possible with tape. TST NOUTFL ; output specified? BNE 30$ ; If not, assume INIT .ASSUME TP.IN EQ 100000 TST SEQPOS ; Magtape specified on input? BMI INVDO2 ; ?BUP-F-Invalid operation for device BR 30$ ...... ; It's a DISK-only operation... ; Disk-to-disk backup... 20$: MOVB GIV.M,R0 ; /NOREWIND specified? BMI INVOPD ; not possible on disk TSTB GIV.R ; /SUBSET? BMI 30$ BIT #FR.OUT,SEQPOS ; No. Foreign Random output? 25$: BNE INVDO2 ; Can't do without /SUBSET ; Check for INITIALIZE option... 30$: TSTB GIV.Z ; INITIALIZE specified? BPL 40$ ; Branch if not. MOVB GIV.M,R0 ; /NOREWIND specified? BISB GIV.F,R0 ; /FILES (truncate) specified? BISB GIV.R,R0 ; /SUBSET specified? INVCM2: BMI INVCMB ; ?BUP-F-Invalid option combination BIS #,R1 ; Set /Z option bit TST NOUTFL ; Input and output entry? BEQ 40$ ; If YES, Treat as BACKUP with INIT TSTB GIV.V ; VERIFY specified? BMI INVCMB ; Not possible during INIT TSTB NONAME ; Filename specified? BPL INVCMD ; Not valid for INIT BIS #,R1 ; No, INIT only BR 70$ ...... ; Check BACKUP operation 40$: TST NOUTFL ; Input and output entry? BNE INVCMD ; No, branch; error 50$: TSTB GIV.I ; DEVICE specified? BPL 60$ ; Branch if not. MOVB GIV.F,R0 ; /FILES (truncate) specified? BISB GIV.R,R0 ; /SUBSET specified? BMI INVCMB TST NONAME ; Input filename specified? BPL INVCMD ; Yes; error BIS #,R1 ; Backup DEVICE BR 70$ 60$: BIS #,R1 ; Backup FILE 70$: MOV R1,OPTACT ; store accumulated option bits RETURN ...... .DSABL LSB .SBTTL CHKLOP - Check /L option ;+ ; DIRECTORY (LIST) command. ; ; Check for invalid option combinations, and set appropriate bits ; on the option action word. ; ; *,,outspc=dev:[spec] (from KMON V5.5) ; ; *outspc=dev:[spec]/L ; ; *dev:[spec]/L ; ; Also allow ; ; *outspc=dev:ssname/L/S ; List of saveset directory ; and ; *outspc=dev:ssname/S,files/L ; or ; *,,outspc=dev:ssname/S,files ; ; Allow /R (/SUBSET) in place of /S if the backup device is NOT ; a magtape. ;- .ENABL LSB CHKLOP: MOVB GIV.F,R0 ; /FILES specified? BISB GIV.G,R0 ; /NOSCAN specified? BISB GIV.I,R0 ; /DEVICE specified? BISB GIV.V,R0 ; /VERIFY specified? BISB GIV.X,R0 ; /RESTORE specified? BISB GIV.Z,R0 ; /INITIALIZE specified? BMI INVCMB ; None of these are any good. TSTB NOUTFL ; Output device? BPL 10$ ; If so, branch MOV #<^RTT0>,OUTDEV ; Put TT0 in appropriate place MOVB #DEV.TT,DEV1 ; and its DSTAT code 10$: BIT #,SEQPOS ; Magtape operation? BEQ 20$ ; branch if not. ; BACKUP/DIRECTORY operation from Tape BIS #,OPTACT ; set magtape bit TSTB GIV.R ; /SUBSET specified? BMI INVDOP ; That's no good on magtape BR 30$ ; BACKUP/DIRECTORY operation from Disk 20$: TSTB GIV.R ; /SUBSET specified? BMI 25$ ; That's ok for Foreign Random BIT #,SEQPOS ; Foreign Random input? INVDO2: BNE INVDOP ; Not allowed. 25$: TSTB GIV.O ; /ONLY:n on disk? BMI INVOPD ; Invalid on disk ; All operations 30$: BIS #,OPTACT ; set directory bits RETURN ...... .DSABL LSB .SBTTL INVCMD - BAD OPTION or ILLEGAL COMMAND LINE abort .ENABL LSB ;+ ; Graveyard ;- INVCMD::MOV #CMD,R1 ; <-F-Invalid command> BR 10$ ...... INVOPD: MOV #IOD,R1 ; <-F-Invalid option for device> BR 10$ ...... INVCMB: MOV #ICM,R1 ; <-F-Invalid option combination> 10$: JMP FATAL ...... INVDCM: MOV #DEQ,R1 ; <-F-Invalid device combination> BR 10$ ...... INVDOP: MOV #IDO,R1 ; <-F-Invalid device for operation> BR 10$ ...... .DSABL LSB .SBTTL CHKXOP - Check /X options ;+ ; RESTORE ; The command line must have an output and input device specification ; and optional filename on the input side. If magtape is specified it ; must be on the input side. ;- .ENABL LSB CHKXOP: MOVB GIV.Z,R0 ; /INITIALIZE specified? BISB GIV.G,R0 ; /NOSCAN specified? BISB GIV.O,R0 ; /ONLY:n specified? BMI INVCMB ; sorry... TST NOUTFL ; In/out entry? BNE INVCMD ; No, branch; error BIT #,SEQPOS ; Magtapes anywhere? BEQ 10$ ; No, skip BPL INVDOP ; Yes, but not on input. ; RESTORE from TAPE was specified TSTB GIV.R ; /SUBSET specified? BMI INVOPD ; that's not possible with tape. BIS #,OPTACT ; Restore from tape BR 30$ ; RESTORE from DISK to disk 10$: MOVB GIV.M,R0 ; /NOREWIND specified? BMI INVOPD ; that's hopeless on disks. TSTB GIV.R ; /SUBSET? BMI 30$ ; If so, Foreign Random input is ok BIT #,SEQPOS ; Foreign Random input? BNE INVDOP ; Not allowed without /SUBSET. ; All RESTORES: ; Determine the nature of the RESTORE operation ; ; Legitimate forms are ; ; /X[/S] Restore file(s) from device image saveset ; /X/I/F[/S] Restore file(s) from device image saveset ; /X/I[/S] Restore BUP image to device ; and /X/F[/S] Restore BUP image to file ; ; /X[/S] is a shorthand for /X/I/F[/S]. /X/F[/S] is a new form that ; allows restoring an old BUP tape file backup to a disk file. 30$: MOV SYDN,SYCHK ; Check for restore to SY: MOV #SYCHK,R1 CALL REALIN ; Get real name of SY: CMP @R1,OUTDEV ; is output device SY:? BNE 40$ ; If not, continue about business. INCB SYSOUT ; Set RESTORING_TO_SY: flag 40$: TSTB GIV.I ; /DEVICE specified? BMI 70$ ; branch if yes TSTB GIV.F ; /FILE specified? BMI 60$ ; branch if yes ; Neither /F nor /I implies BOTH; (/X = /X/I/F) 50$: MOVB #TRUE,GIV.I ; /X: force /I/F (/DEV/FILE) MOVB #TRUE,GIV.F BR 80$ ...... ; BACKUP/RESTORE/FILE inp:[ssname][/S] out:[file] 60$: MOV #,R1 ; FILE image restore BR 110$ ; Go impose restrictions ; /DEVICE was specified 70$: TSTB GIV.F ; /FILE specified? BPL 100$ ; Branch if not. ; BACKUP/RESTORE/DEVICE/FILE (/X/I/F) - a FILE(s) restore operation 80$: MOV #,R1 ; Indicate restore FILE from DEVICE TSTB WILDFG ; Any wildcard specs? BNE 90$ ; If so, no output name allowed. CMPB NISPEC,#1 ; more than 1 input spec? BEQ 130$ ; If not, an output spec is ok. 90$: TSTB NONAME ; Output filename? BPL INVCMD ; Yes, branch; error BR 130$ ; Return with success. ...... ; BACKUP/RESTORE/DEVICE (/X/I) - DEVICE restore ; /S is optional - if specified on an input file, ; allow no non-/S specs. Otherwise, allow one. 100$: MOV #,R1 ; DEVICE restore TSTB NONAME ; Output filename? BPL INVCMD ; Yes, branch; error ; Operation allows input name ONLY if it is a SAVESET name, whether ; or not /S was specified. This is true for /X/I or /X/F. 110$: MOV #1,R0 ; max input filespecs TSTB GIV.S ; Was /S specified? BPL 120$ ; branch if not. CMPB SSSPEC+1,#3 ; is it applied to INPUT SPEC? BLO 120$ ; branch if not. DEC R0 ; If so, allow NO non-/S specs 120$: CMPB NISPEC,R0 ; too many non-/S input specs? BGT INVCMD ; Error if so. 130$: BIS R1,OPTACT ; Set option bits RETURN ...... .DSABL LSB .SBTTL PREMSG - First warning messages ;+ ; Display FOREGROUND LOADED ; If /RESTORE/DEVICE, check for restore over SYSTEM device. ;- .ENABL LSB PREMSG::MOV R0,-(SP) ; Save action routine address MOVB GIV.L,R0 ; /LIST? BMI 50$ ; no messages if so. ; If the foreground is loaded and a non-directory command has been issued, ; say "-Foreground loaded". MOVB GIV.Y,R0 ; /NOQUERY? BISB GIV.R,R0 ; or a /SUBSET command? BMI 10$ ; YES, omit "FG Loaded" on these .GVAL #EMTARE,#$CNFG1 BIT #FJOB$,R0 ; Foreground loaded? BEQ 10$ ; No, branch .PRINT #MSGFOR ; Yes. Advise the brave user. ; Do checks for /RESTORE/DEVICE 10$: BIT #XI$OPT,OPTACT ; /RESTORE/DEVICE? BEQ 50$ ; skip if so. MOVB VONLY,R0 ; Verifying only? BMI 50$ ; That's OK. ; We're RESTORING a DEVICE. TSTB SYSOUT ; Output going to SY:? BNE 20$ ; If so, veto the /NOQUERY. TSTB GIV.Y ; /NOQUERY? BMI 50$ ; skip the questions BR 30$ ; Ask "Are you sure?" 20$: .PRINT #NSY1 ; Warning! Attempting to restore SY! 30$: MOV #OUTDEV,R2 ; R2 -> RAD50 out dev name MOV #NSY2,R1 ; string pointer MOV #1,R5 ; do 1 word CALL SELECT ; convert RAD50 name to ASCII 40$: MOV #NSY2,R1 ; OK to Restore device? CALL ANSWRP ; prompt and get answer BMI 40$ ; Huh? BNE 45$ ; YES was typed. OK.. do it. JMP START2 ; Abort operation. ...... 45$: MOVB SYSOUT,CLOBSY ; SY clobbered if SYSOUT is true. 50$: MOV (SP)+,R0 ; recover action routine adrs RETURN ...... .DSABL LSB .SBTTL REALIN - Get REAL DEVICE name ;+ ; "Ding ding...(sound of woman's voice in loudspeaker) Will the REAL ; Dr. Peterman PLEASE report to neurosurgery, IMMEDIATELY"! ; - The Firesign Theatre ; ; The device handler is fetched and a channel opened, all for the ; purpose of filling the tables on RMON for the device, so we can ; get the physical device name. ; ; On entry, R1 should point to device spec ;- .ENABL LSB REALIN: CLR RBLOCK ; use as success/fail flag MOV @R1,DEVSPC ; Get device for lookup ; Fetch the handler MOV R1,-(SP) MOV NHDRAD,R1 ; At available address, CALL FETHAN ; fetch handler. MOV (SP)+,R1 MOV R0,NHDRAD ; Update handler load address ; Do Non-File-Structured LOOKUP .SERR .LOOKUP #EMTARE,#CHAN0,#DEVSPC,#-1 ; Open channel BCC 10$ DIOERR: MOV #RE1,R1 ; <-F-Directory input error> JMP FATALD ...... ; Call REALDV to do .CSTAT and $DEVTR - Get Physical Device Name 10$: .HERR CALL REALDV ; Go get the device name ; If the output device is being checked, and /R (/SUBSET) was specified, ; now is a good time to ensure that it is NOT a BUP disk. This is only ; necessary when doing a file backup to disk. (The check for TAPE output, ; INITIALIZE, and LIST has already been performed if GIV.R is set.) 20$: TSTB GIV.R ; /SUBSET given? BPL 40$ ; branch if not. CMP R1,#OUTDEV ; Checking output device? BNE 40$ ; Branch if not TSTB SEQDEV ; Testing a tape or KP device? BNE 40$ ; skip it if so MOVB GIV.X,R0 ; Doing /RESTORE? BISB GIV.L,R0 ; was /DIR specified? BISB GIV.I,R0 ; was /DEVICE specified? BNE 40$ ; Branch if any of the above. .READW #EMTARE,#CHAN0,#LBLBUF,#256.,#1 ; Read home block BCC 30$ .ERR #ERRARE,#RE1,LEVEL=ERROR,RETURN=YES,FILE=#DEVSPC ;;;<-E-Directory input error> COM RBLOCK ; Use as flag BR 40$ ...... 30$: MOV LBLBUF+DK.TAG,ODTYPE ; Save output disk type. 40$: .CLOSE #CHAN0 ; Purge channel RETURN ...... .DSABL LSB .SBTTL REALDV - Get physical device name ;+ ; Use the channel information to build a RAD50 device name. ; The resulting name is extended-unit compatible. ; ; When called: R1 -> device name block ;- .ENABL LSB REALDV: .CSTAT #EMTARE,#CHAN0,#LBLBUF ; Get info about channel BCS DIOERR ; error? (should never happen) MOV R2,-(SP) MOV R1,-(SP) MOV #LBLBUF,R0 ; Point to the CSTAT block MOV CST.DU(R0),R1 ; unit number MOV CST.DN(R0),R0 ; device name CALL $DEVTR ; call SYSLIB routine MOV (SP)+,R1 MOV (SP)+,R2 MOV R0,@R1 ; device name RETURN ...... .DSABL LSB .SBTTL STOSPE - Store in/out command specification ;+ ; The input and/or output specifications are taken from the CSI block ; and put into accessable locations (RAD50 - OUTFIL -INFILE). In ; addition these specifications are converted to ASCII and stored ; in another set of locations (OUTASC -INASC )> ;- .ENABL LSB STOSPE::MOV #FSPEC+2,R0 ; Point to output spec MOV #OUTFIL,R1 ; Get store address MOV OUTDEV,(R1)+ MOV (R0)+,(R1)+ ; Store output spec MOV (R0)+,(R1)+ ; ... MOV (R0)+,(R1)+ ; ... MOV #FSPEC,R0 ADD #INSPST+2,R0 ; Get address of input spec MOV INPDEV,(R1)+ MOV (R0)+,(R1)+ ; Save input spec MOV (R0)+,(R1)+ ; ... MOV (R0)+,(R1)+ ; ... ; Convert the RAD50 specs to ASCII equivalents MOV #8.,R5 ; Number of words to be converted MOV #OUTFIL,R2 ; Get RAD50 filespec address MOV #OUTASC,R1 ; Get address to store ASCII CALLR SELECT ...... .DSABL LSB .SBTTL NOWILD - Check for unwanted wildcards ;+ ; ; NOWILD - Checks output filespec for invalid wildcards ; (Spoils R0 and R1) ; ; NOWILI - Checks primary input for invalid wildcards ; (All registers are preserved) ;- .ENABL LSB NOWILI: MOV R0,-(SP) ; Save R0, MOV R1,-(SP) ; and R1, MOV #INASC,R0 ; Point to primary input spec CALL NOWIL1 ; Check it for wildcards MOV (SP)+,R1 ; restore registers, MOV (SP)+,R0 RETURN ...... NOWILD: TSTB NONAME ; A pure wildcard is ok. BMI 40$ MOV #OUTASC,R0 ; point to ASCII output name NOWIL1: MOV #12.,R1 10$: CMPB (R0)+,#'* ; does it contain wildcards? BNE 30$ 20$: MOV #IUW,R1 ; <-F-Invalid use of wildcards> JMP FATAL ...... 30$: CMPB -1(R0),#'% ; does it contain wildcards? BEQ 20$ DEC R1 BGT 10$ 40$: RETURN ...... .DSABL LSB .SBTTL DISPCH - Dispatch to appropriate action routine ;+ ; The option action flag is examined, if the command belongs to ; group B then the input and output filespec in rad50 are converted ; to ascii, for group A only the device rad50 is converted. If the ; command is FILE RESTORE or FILE BACKUP and an output filename is ; missing then the input filename is used with the .BUP extension. ; The device logical name is converted into its physical name. ; The option is determined and a call to the appropriate module ; is executed. On return from the module an unconditional jump ; is performed to the start of the central code. ; ;- .ENABL LSB DISPCH::TSTB OPTACT ; Group-B options? BMI GROUPB ; Yes, branch ; The command is either /Z (by itself, with no input spec) or /L TSTB GIV.Z ; /Z option? BPL 10$ ; No, branch TST NOUTFL ; Input device? BPL 10$ ; Yes, branch MOV FSPEC,INFIL ; Get output dev into input BR 20$ ; Go convert 10$: MOV #FSPEC,R1 ; NOT /Z or INPUT specified. MOV INSPST(R1),INFIL ; Move input device into ; ...proper location 20$: MOV #INFIL,R1 ; Get input dev adrs in R1 CALL REALIN ; Get real device name TST RBLOCK ; Was device not there? BEQ 30$ ; If not, get out. JMP 200$ ...... 30$: BIT #Z$OPT,OPTACT ; Initialize? BEQ 50$ ; Branch if not BIT #T$OPT,OPTACT ; INIT - Tape operation? BNE 40$ ; Branch if so INIJMP: MOV #INITI,R0 ; INITIALIZE DISK RETURN ...... 40$: MOV INFIL,OUTFIL ; (BUPMT1 thinks of it as out) MOV #INASC,R0 MOV #OUTASC,R1 MOVB (R0)+,(R1)+ ; Move device name too MOVB (R0)+,(R1)+ MOVB (R0)+,(R1)+ TBJMP: MOV #TBAC,R0 ; Call TAPE BACKUP module RETURN ...... ; Directory (list) option 50$: CALL STOSPE ; Store INPUT and OUTPUT specs TST RBLOCK ; Device not ready? BMI 120$ ; (LOOKUP fail?) CALL NOWILD ; Prevent embarassing output files BIT #T$OPT,OPTACT ; DIR - Tape operation? BEQ DIRJMP ; If not, do DISK DIR TSTB GIV.S ; /BACK/DIR Mxn:/SAVESET? BPL 55$ ; if not, don't need WF CALL FETWFD ; Fetch WF handler 55$: MOV #TDIR,R0 ; Call TAPE DIRECTORY module RETURN ...... DIRJMP: MOV #DIREC,R0 ; Call DISK DIRECTORY module RETURN ...... ; The requested operation is BACKUP or RESTORE. Check to see if it's ; an operation that requires an output filespec, and fill it in if it ; is not supplied. GROUPB: CALL FETWFD ; Fetch WF handler TSTB NONAME ; Output filename supplied? BPL 100$ ; If so, branch MOV #FSPEC,R0 ; R0-> output spec area MOV R0,R1 ADD #INSPST,R1 ; R1-> input spec BIT #,OPTACT ; Output filespec needed? BEQ 90$ ; No, branch. TST (R1)+ ; R1-> input filename BIT #,OPTACT ; Is it a FILE BACKUP? BEQ 80$ ; No. Must be RESTORE FILE. MOV #DEFNAM,R1 ; R1-> default BACKUP.BUP name 80$: TST (R0)+ ; R0-> output filename MOV (R1)+,(R0)+ ; Put input filename... MOV (R1)+,(R0)+ ; ...into output spec BR 100$ ; (ext is handled elsewhere) ...... ; If operation is BACKUP, was /DEVICE specified? If so, and no output ; name was given, substitute the input device name, like "LD2.BUP". 90$: BIT #I$OPT,OPTACT ; Device backup? BEQ 100$ ; If not, continue below. TST (R0)+ ; Point to output filename MOV INPDEV,@R0 ; Use in/dev as out/filename ; If operation is /RESTORE/DEVICE, and no input saveset name is given, ; use the output device name as the default. 100$: BIT #XI$OPT,OPTACT ; /RESTORE/DEVICE? BEQ 110$ ; branch if not TST NONAME ; input name supplied? BPL 110$ ; branch if it was. MOV FSPEC,FSPEC+INSPST+2 ; move outdev to inp name ; Common code for BACKUP and RESTORE 110$: CALL STOSPE ; Store the command spec, cvt to ASCII MOV #OUTASC,R1 MOV #DEVICE,R4 CALL SETNAM ; Store output name in prompt message TST RBLOCK ; device not ready? 120$: BMI 200$ ; (LOOKUP fail?) ; Check for invalid wildcards in OUTPUT saveset or file name. CALL NOWILD ; Ensure that backups to a /SUBSET file aren't going to a ; BUP-formatted disk. 160$: BIT #NO$OPT,OPTACT ; BACKUP FILE operation? BEQ 180$ ; Branch if not. TSTB GIV.R ; BACKUP/SUBSET? BPL 170$ ; Branch if not. TST ODTYPE ; If so, is output disk a BUP disk? BEQ 170$ ; Hopefully not. MOV #NRT,R1 ; If it is, abort now. (Not RT-11) MOV OUTFIL,DEVSPC ; Device is output for err msg JMP FATALD ...... ; Open a BUP temporary file on the WF or SY device, and store ; a container directory with all of the specified filenames. 170$: CALL MAKDIR ; Make container in temp file BCC 180$ ; If success, go ahead. CALL BAKDON ; print list of files not found JMP START2 ; and abort. ...... 180$: TSTB GIV.X ; Restore? BPL 190$ TSTB VONLY ; /VERIFY:ONLY? BMI 190$ ; branch if so MOVB #WRDISK,VONLY ; Otherwise, grant special permission. 190$: BIT #T$OPT,OPTACT ; Tape operation? BNE 210$ ; Yes, branch ; Operation is to/from DISK BIT #XIF$OP,OPTACT ; /X/I/F ? BNE XIFJMP ; Yes branch BIT #,OPTACT ; /X option? BNE XJMP ; Yes, branch BIT #,OPTACT ; Image copy? BNE IMAJMP ; Yes, branch 200$: CLR R0 ; Indicate None-of-the-above RETURN ...... ; Operation is to/from TAPE 210$: BIT #,OPTACT ; File or Image backup? BEQ 220$ ; No, branch JMP TBJMP ; Yes, do tape backup ...... 220$: BIT #XIF$OP,OPTACT ; /X/I/F ? BNE TXIFJP ; Yes, branch BIT #,OPTACT ; /X option? BEQ 200$ ; No. None of them. TXJMP: MOV #TRES,R0 ; Call TAPE RESTORE module RETURN ...... XIFJMP: XJMP: MOV #XBACK,R0 ; Call DISK RESTORE module RETURN ...... IMAJMP: MOV #IMAGE,R0 ; Call DISK BACKUP module RETURN ...... TXIFJP: MOV #TFRES,R0 ; Call TAPE FILE RESTORE module RETURN ...... .DSABL LSB .SBTTL FETWFD - Fetch workfile device handler ;+ ; FETWFD - Fetch workfile device handler ;- .ENABL LSB FETWFD: .DSTATUS #EMTARE,#TMPFIL ; Does "WF:" exist? BCS 30$ ; Branch if not. TST EMTARE+4 ; Is WF loaded? BNE 20$ ; Branch if so. MOV NHDRAD,R1 ; At available address, MOV TMPFIL,DEVSPC ; for this device, CALL FETHAN ; fetch handler. 10$: MOV R0,NHDRAD ; Update handler load address 20$: RETURN ...... 30$: MOV SYDN,TMPFIL ; store "SY" in TMPFIL dblk RETURN ...... .DSABL LSB ;+ ; BUPCMD Patch Area - Use only in case of emergency. ;- .PSECT PATCMD,I PATCM:: .BLKW 32. ; This should be plenty. .END