.TITLE BAKUP - INCREMENTAL FILE BACK-UP UTILITY .IDENT /V02A/ .LIST MEB .NLIST BEX .SBTTL TITLE PAGE AND INTRODUCTION ; ;********************************************************************** ; ; I N C R E M E N T A L B A C K - U P U T I L I T Y ; ; VERSION V02 ; ; K.J. CROSS 15-JUL-77 ; ; MODIFIED BY K.J. CROSS 22-MAR-78 ; V02 - EXECUTE RUN$ INSTEAD OF MRKT$ TO WAIT ; UNTIL TIME TO GO ; ; K.J. CROSS 11-MAY-78 ; MAKE BACKUP START IMMEDIATELY ON "BAK /-WAIT" ; ; ; ; THIS PROGRAM PERFORMS AN INCREMENTAL BACKUP AT VARIOUS TIMES OF ; THE DAY. AN INCREMENTAL BACKUP IS THE PROCEDURE OF SAVING ALL ; FILES CREATED SINCE THE LAST BACKUP ON A BACKUP MEDIUM, USUALLY MAG TAPE. ; ; WHEN THIS PROGRAM IS RUN, IT WILL PERFORM THE FOLLOWING STEPS: ; ; 1. WAIT UNTIL THE SPECIFIED TIME TO RUN (SEE BELOW). ; ; 2. WHEN IT IS TIME FOR THE INCREMENTAL BACKUP, ISSUE A ; WARNING MESSAGE TO ALL TERMINALS THAT AN INCREMENTAL ; BACKUP WILL START IN 5 MINUTES. THIS GIVES USERS A ; CHANCE TO CLEAN UP THEIR DISK AREAS A LITTLE TO MINIMIZE ; THE NUMBER OF "JUNK" FILES THAT ARE SAVED. ; ; 3. IF THE INITIATING TERMINAL ("TI:") IS NOT PRIVILEGED, ; MAKE HIM PRIVILEGED EITHER BY LOGGING ONTO A PRIVILEGED ; ACCOUNT (IF TI: IS NOT LOGGED ON), OR SETTING THE PRIVILEGED ; BIT IN THE UCB OF TI:. ; ; 4. START THE INDIRECT COMMAND FILE "SY:[1,2]BACKUP.CMD" ; OR "SY:[1,2]BACKUPN.CMD" IF THE USER SPECIFIED "/NOOPR" ; IN THE COMMAND LINE (SEE BELOW). ; ; 5. EXIT. ; ; THIS PROGRAM SHOULD BE ASSEMBLED AS FOLLOWS: ; ; MAC BAKUP,BAKUP=[1,1]EXEMC/ML,BAKUP ; ; AND TASK BUILT AS FOLLOWS: ; ; TKB BAKUP/PR/-FP,BAKUP=BAKUP,GTTSK,GTMNM,LB:[1,54]RSX11M.STB/SS ; / ; UNITS=0 ; TASK=...BAK ; PRI=35. ; // ; ; THIS TASK IS PRIVILEGED BECAUSE IT ISSUES COMMANDS TO MCR. THE USER ; MUST ALSO BE PRIVILEGED SINCE THIS TASK ISSUES "BRO ALL:" COMMANDS. ; ; IF THE USER ON TI: IS LOGGED IN UNPRIVILEGED, HE WILL BE GIVEN ; A MESSAGE THAT HE HAS BEEN MADE PRIVILEGED. ; ; BAK IS INVOKED BY THE FOLLOWING COMMAND LINE: ; ; BAK [/TI[HH:MM]] [/NOOPR] ; ; OR ; ; BAK /-WAIT ; ; THE /TI SWITCH, IF SPECIFIED WITH NO ARGUMENTS, TELLS BAK TO START ; ISSUING THE 5 MINUTE WARNING MESSAGE IMMEDIATELY, THEN ANOTHER MESSAGE ; AT 3 MINUTES AND 1 MINUTE, THEN START THE INDIRECT COMMAND FILE. ; ; IF THE /NOWAIT SWITCH ("/NOWAIT" OR "/-WAIT") IS SPECIFIED, THEN THE ; 5 MINUTE WARNING INTERVAL IS BYPASSED AND BACKUP BEGINS IMMEDIATELY. ; ; /TI CAN BE SPECIFIED WITH TWO DECIMAL NUMERIC ARGUMENTS (HH:MM) ; WHICH GIVE THE HOUR AND MINUTE THAT THE INDIRECT COMMAND FILE IS ; TO BE RUN. BAK WILL RESCHEDULE ITSELF TO RUN AT THE SPECIFIED ; TIME OF DAY, THEN ISSUE THE 5 MINUTE, 3 MINUTE, AND 1 MINUTE WARNING ; MESSAGES, THEN START THE INDIRECT COMMAND FILE. ; ; IN ANY OF THE ABOVE CASES, THE "/NOOPR" (OR /-OP) SWITCH MAY BE ; SPECIFIED, INDICATING THAT THE "BACKUPN.CMD" COMMAND FILE SHOULD ; BE RUN INSTEAD OF "BACKUP.CMD". "BACKUPN.CMD" REQUIRES NO OPERATOR ; BE PRESENT DURING RUNNING AND ASSUMES THE FOLLOWING CONDITIONS: ; ; 1. THE APPROPRIATE TAPE IS LOADED AND MOUNTED ONTO BK:. ; ; 2. THE DISKS TO BE BACKED UP ARE MOUNTED ; AND THAT NO OTHER DISKS NEED BACKING UP. ; ;********************************************************************** .SBTTL MACRO DEFINITIONS ; ; LOCAL MACRO DEFINITIONS ; ; ; PUTMCR MACRO - MACRO USED TO SET UP THE CALL TO SUBROUTINE "GIVMCR". ; R0 SI PRESERVED ON THE STACK, THE ADDRESS OF THE MCR STRING IS ; LOADED INTO R5, "GIVMCR" IS CALLED, AND R0 IS RESTORED. ; ; THE FIRST TIME THE MACRO IS INVOKED, THE "PUTERR" ENTRY POINT ; IS ESTABLISHED TO HANDLE ERRORS FROM GIVMCR. THEREAFTER, THE ; MACRO INSERTS A BRANCH (OR JUMP) TO PUTERR ON ERRORS. ; P$$ERR = 0 ;INITIALIZE PUTMCR VARIABLE .MACRO PUTMCR MCRSTR,?ER ;OUTPUT "MCRSTR" TO MCR MOV R0,-(SP) ;SAVE R0 MOV #MCRSTR,R5 ;GET ADDRESS OF THE MCR STRING JSR PC,GIVMCR ;PASS IT ON TO MCR .IF NE P$$ERR $$$ = .-PUTERR .IF GE $$$-400 BCC ER ;NO ERROR IF CC JMP PUTERR ;ERROR IF CS .IFF BCS PUTERR ;CS IF ERROR OCCURRED .ENDC .IFF P$$ERR = P$$ERR + 1 BCC ER ;IF CC, NO ERRORS PUTERR: MOV #BRO1,R5 ;TRY TO OUTPUT BRO1 JSR PC,GIVMCR ; TO TELL THE WORLD OUR PROBLEMS EXIT$S ;AND QUIT .ENDC ER: MOV (SP)+,R0 ;RESTORE R0 .ENDM ; ; CALL MACRO - IF "SUBR" IS $SWSTK, THEN THE CALL IS ; CONVERTED INTO AN EMT AND THE ARGUMENT IS PLACED AFTER THE EMT. ; .MACRO CALL SUBR,ARG ;SUBROUTINE CALL .IF IDN SUBR,<$SWSTK> EMT ^O<376> .WORD ARG .MEXIT .ENDC JSR PC,SUBR .ENDM ; ; MACRO CALLS ; .MCALL WTSE$,GMCR$,CSI$,CSI$SW,CSI$SV,CSI$ND .MCALL DIR$,CSI$2,CSI$1,GTIM$C,MRKT$S,MRKT$C .MCALL EXIT$S,UCBDF$,DCBDF$,TCBDF$,WSIG$S,RUN$S UCBDF$ <:>,<=> ;DEFINE ALL SYMBOLS GLOBALLY DCBDF$ <:>,<=> TCBDF$ <:>,<=> .SBTTL LOCAL DATA ; ; LOCAL DEFINITIONS ; TILUN = 1 ;LOGICAL UNIT NO. FOR TI: TIEFL = 1 ;EVENT FLAG TO USE WITH TI: WAITFL = 2 ;EVENT FLAG FOR MARK TIME TIMSK = 1 ;MASK BIT FOR /TI SWITCH OPRMSK = 2 ;MASK BIT FOR /NOOPR SWITCH NOWAIT = 4 ;MASK BIT FOR /NOWAIT SWITCH TIMBUF = MCRLN + G.MCRB ;BUFFER USED FOR GTIM$ TERM = 15 ;MCR COMMAND TERMINATOR (CARRIAGE RETURN) ; ; LOCAL DATA ; .PSECT DATA,D BRO1: .ASCIZ 'BRO ALL: BAK -- ERROR IN PUTMCR - BACKUP ABORTED' BRO2: .ASCII 'BRO LOG: BACKUP WILL START IN ' BRO2M: .ASCIZ '5 MINUTES' BRO2ND = . ;END OF BROADCAST MESSAGE #2 BRO3: .ASCIZ 'BRO ALL: BAK -- AT. NOT INSTALLED - BACKUP ABORTED' BRO4: .ASCIZ 'BRO TI: BAK -- CONGRATULATIONS - YOU ARE NOW PRIVILEGED.' BRO5: .ASCIZ 'BRO ALL: BAK -- BACKUP IS STARTING NOW...' BRO6: .ASCIZ 'BRO TI: BAK -- AT. BUSY - WILL WAIT 1 MINUTE' BRO7: .ASCIZ 'BRO ALL: BAK -- AT. BUSY - BACKUP ABORTED' BRO8: .ASCIZ 'BRO TI: BAK -- *FATAL* COMMAND LINE ERROR' HELLO: .ASCIZ 'HELLO THTF/SYSTEM' CMDFIL: .ASCII '@LB0:[1,2]BACKUP' IFOPR: .ASCIZ ' .CMD' .EVEN WAIT: WTSE$ WAITFL ;WAIT FOR TIMEOUT TIUCB: .BLKW 1 ;UCB ADDRESS OF TI: AT.: .RAD50 /AT. / ;INDIRECT COMMAND FILE PROCESSOR TASK BAKTSK: .RAD50 /...BAK/ ;BACKUP TASK NAME FOR RUN$ AT.ACT: .BLKW 1 ;0=AT. IS NOT ACTIVE WASPRV: .WORD 0 ;0=TI: WAS PRIVILEGED MCRLN: GMCR$ ;MCR COMMAND LINE CSI$ ;DEFINE CSI CONTROL BLOCK OFFSETS CSIBLK: .BLKB C.SIZE ;ALLOCATE STORAGE FOR CSI BLOCK CSISW: CSI$SW TI,TIMSK,CSMSK,SET,,SWTBL ;/TI:HH:MM CSI$SW OPR,OPRMSK,CSMSK,CLEAR,NEG ;/NOOPR CSI$SW WA,NOWAIT,CSMSK,CLEAR,NEG ;/NOWAIT CSI$ND SWTBL: CSI$SV DECIMAL,HOURS,2 ;HOURS VALUE CSI$SV DECIMAL,MIN,2 ;MINUTES VALUE CSI$ND CSMSK: .WORD 0 ;SWITCH BITS SET IN HERE HOURS: .WORD 0 ;HOURS MIN: .WORD 0 ;MINUTES .SBTTL MAIN PROGRAM .ENABL LSB ; ; MAIN ROUTINE - ENTRY POINT. ; ; START BY READING THE COMMAND LINE. IT IS ASSUMED THAT THE TASK IS ; INITIATED VIA "BAK [/TI:HH:MM][/-OP]" COMMAND LINE. IF IT WASN'T (I.E. ; IT WAS STARTED VIA "RUN" COMMAND), THEN ASSUME THE USER WANTS TO ; START IN 5 MINUTES. THE OTHER OPTIONS ARE: ; ; COMMAND LINE OPERATION ; ------------ --------- ; ; BAK /NOWAIT START BACKUP IMMEDIATELY ; BAK /TI START BACKUP IN 5 MINUTES, ISSUING APPROPRIATE ; WARNING MESSAGES TO TERMINALS ; BAK /TI:HH:MM START BACKUP 5 MINUTES AFTER THE SPECIFIED TIME ; OF DAY, I.E. START MESSAGES AT HH:MM ; BAK /-OP WHEN USED WITH ANY OF THE ABOVE COMMAND LINES, ; USE "BACKUPN.CMD", WHICH REQUIRES NO OPERATOR ; INTERVENTION TO RUN ; .PSECT BAKUP:: MOV $TKTCB,R0 ;GET ADDRESS OF OUR OWN TCB MOV T.UCB(R0),R0 ;GET UCB OF TI: 1$: MOV U.RED(R0),R0 ;FOLLOW REDIRECT CHAIN CMP R0,U.RED(R0) ;AT END OF CHAIN? BNE 1$ ;IF NE, NO MOV R0,TIUCB ;SAVE UCB ADDRESS DIR$ #MCRLN ;READ THE COMMAND LINE MOV @#$DSW,R1 ;GET BYTE COUNT BLT 7$ ;IF LT, NO - START IMMEDIATELY MOV #MCRLN+G.MCRB,R2 ;GET START OF COMMAND LINE BUFFER 5$: CMPB #' ,(R2)+ ;IS IT A BLANK? BEQ 10$ ;IF EQ, YES SOB R1,5$ ;ANY CHARACTERS LEFT IN THE LINE? 7$: JMP START ;NOPE - START 5 MINUTE TIMEOUT IMMEDIATELY 10$: DEC R1 ;SET R1 TO CORRECT STRING LENGTH CSI$1 #CSIBLK,R2,R1 ;INITIALIZE THE CSI BLOCK BCC 11$ ;IF CC, NO PROBLEMS 12$: PUTMCR BRO8 ;"BRO TI: COMMAND LINE ERROR" ERRXT: TST WASPRV ;WAS TI: PRIVILEGED BEFORE? BEQ 63$ ;IF EQ, YES OR DON'T KNOW MOV TIUCB,R0 ;GET UCB OF TI: BIC #U2.PRV,U.CW2(R0) ;SET BACK TO UNPRIVILEGED 63$: EXIT$S ;EXIT FAST 11$: CSI$2 #CSIBLK,OUTPUT,#CSISW ;CHECK FOR SWITCHES BCS 12$ ;IF CS, THERE WAS AN ERROR BIT #NOWAIT,CSMSK ;WAS /NOWAIT OR /-WAIT SET? BEQ 15$ ;IF EQ, NO JMP BEGIN ;START NOW!!! 15$: BIT #TIMSK,CSMSK ;WAS /TI SET? BEQ 7$ ;IF EQ, NO - START IMMEDIATELY MOV HOURS,R1 ;GET TIME IN HOURS BLT 12$ ;IF LT, RIDICULOUS MUL #60.,R1 ; * 60. FOR MINUTES ADD MIN,R1 ;TIME TO START IN MINUTES FROM MIDNIGHT BEQ START ;IF EQ (/TI OR /TI:0:0), START 5 MIN. COUNTDOWN GTIM$C TIMBUF ;READ PRESENT TIME (USE MCR LINE BUFFER) MOV TIMBUF+G.TIHR,R3 ;GET PRESENT HOUR MUL #60.,R3 ; * 60. FOR MINUTES ADD TIMBUF+G.TIMI,R3 ;R3 = TIME IN MINUTES FROM MIDNIGHT SUB R3,R1 ;COMPUTE TIME UNTIL STARTUP BEQ START ;IF ZERO, GO!!! BGT 20$ ;IF >0, START THE DELAY ADD #<24.*60.>,R1 ;ADD 24 HOURS TO THE DIFFERENCE 20$: RUN$S #BAKTSK,,,#1,#2,R1,#3 ;RUN THE TASK (R1) MINUTES FROM NOW EXIT$S ;AND GET OUT OF MEMORY .DSABL LSB .SBTTL START 5 MINUTE TIMEOUT .ENABL LSB ; ; IT IS TIME TO START THE BACKUP - OR AT LEAST START STARTING IT. ; ; IT IS NECESSARY AT THIS POINT TO INSURE THAT TI: IS PRIVILEGED. ; START:: CALL MAKPRV ;MAKE SURE WE'RE PRIVILEGED MOVB #'5,BRO2M ;SET MESSAGE TO READ 5 MINUTES PUTMCR BRO2 ;"BRO ALL:BACKUP IN 5 MINUTES" 40$: MRKT$C WAITFL,2,3 ;WAIT 2 MINUTES DIR$ #WAIT ;ZZZZZZZZZZZZZZZ... ; ; 3 MINUTES TO GO - CHECK FOR PRIVILEGES AGAIN. ; CALL MAKPRV ;MAKE SURE WE'RE PRIVILEGED MOVB #'3,BRO2M ;SET MESSAGE TO READ 3 MINUTES PUTMCR BRO2 ;"BRO ALL:BACKUP IN 3 MINUTES" 50$: MRKT$C WAITFL,2,3 ;BACK TO SLEEP FOR 2 MINUTES DIR$ #WAIT ; ... ; ; 1 MINUTE TO GO ... ; CALL MAKPRV ;MAKE SURE WE'RE PRIVILEGED MOVB #'1,BRO2M ;SET MESSAGE TO READ 1 MINUTE CLRB BRO2ND-2 ;NO PLURAL FOR 1 MINUTE MOVB #TERM,BRO2ND-3 ;PUT THE TERMINATOR AT THE END PUTMCR BRO2 ;"BRO ALL:BACKUP IN 1 MINUTE" 60$: MRKT$C WAITFL,1,3 ;WAIT FOR 1 MORE MINUTE DIR$ #WAIT ; ... .DSABL LSB .SBTTL INITIATE THE BACKUP .ENABL LSB ; ; TIME TO BACKUP NOW!!!! ; BEGIN:: CALL MAKPRV ;MAKE SURE WE'RE PRIVILEGED ; ; CHECK TO SEE IF AT. (INDIRECT COMMAND FILE PROCESSOR) IS RUNNING ; WITH THE SAME TI: AS US. IF IT IS, ISSUE A WARNING MESSAGE AND ; WAIT FOR 1 MINUTE. IF IT IS STILL BUSY, ISSUE A MESSAGE AND QUIT. ; 29$: CLR AT.ACT ;SET FLAG THAT AT. IS NOT ACTIVE 30$: MOV #AT.+4,R3 ;SET UP ADDRESS OF TASK NAME CLR -(R3) ;TOP 3 CHARACTERS ARE SPACES MOV #^RAT.,-(R3) ;TASK NAME = .RAD50 /AT. / CALL $GTTSK ;GET THE TCB OF AT. BCC 40$ ;IF CARRY SET, AT. NOT FOUND PUTMCR BRO3 ;OUTPUT TEARFUL MESSAGE JMP ERRXT ;AND GIVE IT UP 40$: CMP TIUCB,T.UCB(R0) ;DOES AT. HAVE SAME TI: AS US? BNE 50$ ;IF NE, NO - PROCEED TST T.STAT(R0) ;IS AT. ACTIVE? BMI 50$ ;IF MI, NO TST AT.ACT ;WAS IT ACTIVE BEFORE? BNE 45$ ;IF NE, YES - QUIT TRYING MRKT$C WAITFL,1,3 ;SET WAIT FOR 1 MINUTE PUTMCR BRO6 ;WARN THE WORLD WHAT IS HAPPENING MOV SP,AT.ACT ;SET AT.ACT NON-ZERO DIR$ #WAIT ;AND WAIT FOR OUR MINUTE TO ELAPSE BR 30$ ;GO CHECK AT. ONCE MORE 45$: PUTMCR BRO7 ;"BRO ALL: AT. ACTIVE - BACKUP ABORTED" JMP ERRXT ;GO HOME 50$: PUTMCR BRO5 ;"BRO ALL: BACKUP STARTING NOW" ; ; NOW WE WANT TO START THE COMMAND FILE "SY:[1,2]BACKUP.CMD". ; HOWEVER, SINCE WE DON'T KNOW IF THE USER HAS SOME OTHER DEVICE ; ASSIGNED TO SY:, WE NEED THE REAL NAME OF SY:. SO, LOOK UP THE ; DEVICE NAME THROUGH THE UCB OF SY: AND INSERT THE PHYSICAL DEVICE ; NAME IN THE STRING, E.G. "@DK0:[1,2]BACKUP.CMD". ; 20$: MOV #.SY0,R0 ;GET UCB ADDRESS OF SY: 21$: MOV U.RED(R0),R0 ;FOLLOW REDIRECT CMP R0,U.RED(R0) ;FOUND THE END? BNE 21$ ;IF NE, NO MOVB U.UNIT(R0),R1 ;GET THE UNIT NUMBER BIS #'0,R1 ;CONVERT TO ASCII MOVB R1,CMDFIL+3 ;PUT UNIT NUMBER INTO STRING MOV U.DCB(R0),R0 ;GET ADDRESS OF DCB MOVB D.NAM(R0),CMDFIL+1 ;MOVE THE GENERIC NAME (E.G. "DK") MOVB D.NAM+1(R0),CMDFIL+2 ; INTO THE COMMAND STRING BIT #OPRMSK,CSMSK ;WAS /NOOPR SPECIFIED? BEQ 99$ ;IF EQ, NO MOVB #'N,IFOPR ;IF SO, EXECUTE "@SY:[1,2]BACKUPN.CMD" 99$: PUTMCR CMDFIL ;"@XXY:[1,2]BACKUP.CMD" EXIT$S ;OUR JOB IS DONE .DSABL LSB .SBTTL GIVMCR - PASS COMMAND LINE TO MCR ; ; GIVMCR - SUBROUTINE TO OUTPUT THE STRING ADDRESS BY R5 ; TO MCR. THE STRING IS ASSUMED TO BE TERMINATED BY A NULL. ; GIVMCR:: CALL $SWSTK,15$ ;SWITCH TO SYSTEM STATE MOV #84.,R1 ;LENGTH OF MCR BUFFER CALL $ALOCB ;GET A BUFFER FOR MCR LINE BCC 5$ ;IF CC, NO PROBLEMS MOV @$HEADR,R0 ;GET OUR USER SP INC 6(R0) ;SET USER MODE CARRY BIT BR 15$ ;EXIT 5$: MOV R0,R1 ;COPY BUFFER ADDRESS CLR (R0)+ ;CLEAR LINK WORD MOV TIUCB,(R0)+ ;SET UCB OF TI: IN BUFFER 10$: MOVB (R5)+,(R0)+ ;MOVE THE MCR COMMAND LINE BNE 10$ ; INTO THE BUFFER MOV TIUCB,R4 ;GET TI: UCB ADDRESS BIS #U2.AT.,U.CW2(R4) ;SET BIT TO SYNCHRONIZE WITH MCR CALL $QMCRL ;QUEUE COMMAND TO MCR 15$: RETURN ;ALL DONE - RETURN TO USER STATE .SBTTL LOGON - LOG ONTO THE SYSTEM AS PRIVILEGED ; ; LOGON - THIS SUBROUTINE LOGS THE TERMINAL ONTO THE SYSTEM ; UNDER A PRIVILEGED ACCOUNT. IT ISSUES THE LOGON COMMAND, ; AND THEN WAITS UNTIL THE TERMINAL IS LOGGED ON. ; LOGON:: PUTMCR HELLO ;ISSUE THE LOGON COMMAND TO MCR 5$: BIT #U2.LOG,U.CW2(R0) ;LOGGED ON YET? BEQ 10$ ;IF EQ, YES WSIG$S ;IF NOT, WAIT A WHILE BR 5$ ; AND TRY AGAIN 10$: RETURN ;LOGGED ON - RETURN .SBTTL MAKPRV - FORCE THE TERMINAL TO BE PRIVILEGED ; ; MAKPRV - THIS ROUTINE FORCES THE TERMINAL TO BE PRIVILEGED. ; ; THIS IS ACTUALLY DONE BY SETTING THE "U2.PRV" BIT IN U.CW2 ; OF THE TI: UCB. THE USER THEN BECOMES PRIVILEGED. THE FLAG ; WORD "WASPRV" IS USED TO SIGNIFY THE FACT THAT THE USER WASN'T ; PRIVILEGED INITIALLY, AND SHOULD BE SET BACK UNPRIVILEGED IF ; THE PROGRAM TERMINATES ABNORMALLY FOR SOME REASON. ; MAKPRV:: MOV TIUCB,R0 ;GET UCB OF TI: BIT #U2.LOG,U.CW2(R0) ;LOGGED ON? BEQ 10$ ;IF EQ, YES 5$: CALL LOGON ;LOG ON PRIVILEGED 10$: BIT #U2.PRV,U.CW2(R0) ;PRIVILEGED? BNE 20$ ;IF NE, YES MOV SP,WASPRV ;SET FLAG SAYING TI: WASN'T PRIVILEGED BIS #U2.PRV,U.CW2(R0) ;MAKE HIM PRIVILEGED ; PUTMCR BRO4 ;"BRO TI: YOU ARE NOW PRIVILEGED" 20$: RETURN ;WE ARE NOW PRIVILEGED .END BAKUP ;THAT'S ALL, FOLKS...