; PROGRAM: PROTECT ; VERSION: 3.0 ; DATE: 18 May 84 ; AUTHOR: RICHARD CONN ; PREVIOUS VERSIONS: 2.0 (16 Jan 83) ; PREVIOUS VERSIONS: 1.3 (6 Jan 83), 1.2 (7 Dec 82), 1.1 (10 NOV 82) ; PREVIOUS VERSION: PROTECT.ASM Version 1.0 (26 OCT 81) VERS equ 30 z3env SET 0f400h ; ; PROTECT Command -- ; PROTECT is used to set the file protection and tag attribute bits ; for CP/M 2.x files in the ZCPR3 environment. It is invoked via command ; lines of the following forms: ; PROTECT dir:afn1,dir:afn2,... keys <-- Set unconditionally ; PROTECT dir:afn1,... keys I <-- Inspect Mode ; PROTECT dir:afn1,... C <-- Set each ufn ; ; In the above examples, the reference 'keys' is a string of zero or ; more characters which may be any of the following: ; ; A <-- Set AR Attribute ; R <-- Set R/O Attribute (no R sets R/W) ; S <-- Set SYS Attribute (no S sets Non-System) ; n <-- Set Tag Attribute (1 <= n <= 8) ; ; Examples: ; PROTECT *.COM RS <-- Sets all COM files to R/O SYStem ; PROTECT *.COM RSI <-- Same, with user approval ; PROTECT *.COM C <-- Allows user to specify for each ; PROTECT MYPROG.COM 1R <-- Sets Tag Bit 1 and R/O Attribute ; FALSE EQU 0 TRUE EQU NOT FALSE ESIZE EQU 16 ; SIZE OF DIR ENTRY (FROM SYSLIB DIRF ROUTINE) EXT DIRQ ; DIRECTORY PROCESSOR EXT Z3INIT ; INIT BUFFERS EXT ZFNAME ; FILE NAME PROCESSOR EXT Z3LOG ; LOG INTO Z3 DU EXT BBLINE ; INPUT LINE EDITOR EXT INITFCB ; INIT FCB EXT BDOS ; BDOS ENTRY EXT PUTUD ; SAVE CURRENT USER/DISK EXT GETUD ; RESTORE CURRENT USER/DISK EXT MOVEB ; COPY ROUTINE EXT PHLDC ; PRINT HL AS DECIMAL CHARS EXT PRINT ; PRINT ROUTINE EXT COUT ; CONSOLE OUTPUT ROUTINE EXT CIN ; CONSOLE INPUT ROUTINE EXT CAPS ; CAPITALIZE ROUTINE EXT CRLF ; NEW LINE ROUTINE EXT FILLB ; FILL ROUTINE EXT CODEND ; CODE END COMPUTATION ROUTINE ; ; CP/M EQUATES ; CPM EQU 0 ; WARM BOOT FCB EQU 5CH ; FCB BUFF EQU 80H ; INPUT LINE BUFFER CR EQU 13 ; LF EQU 10 ; ; ; Environment Definition ; if z3env ne 0 ; ; External ZCPR3 Environment Descriptor ; jmp start db 'Z3ENV' ;This is a ZCPR3 Utility db 1 ;External Environment Descriptor z3eadr: dw z3env start: lhld z3eadr ;pt to ZCPR3 environment ; else ; ; Internal ZCPR3 Environment Descriptor ; MACLIB Z3BASE.LIB MACLIB SYSENV.LIB z3eadr: jmp start SYSENV start: lxi h,z3eadr ;pt to ZCPR3 environment endif ; ; Start of Program -- Initialize ZCPR3 Environment ; call z3init ;initialize the ZCPR3 Env and the VLIB Env LXI H,0 ; GET STACK PTR DAD SP SHLD STACK ; SAVE IT CALL CODEND ; DETERMINE FREE SPACE SHLD CMDLNE ; COMMAND LINE BUFFER LXI D,100H ; BUFFER SIZE DAD D SHLD DIRBUF ; DIR BUFFER SPHL ; SET SP CALL PUTUD ; SAVE CURRENT USER/DISK AWAY CALL PRINT DB 'PROTECT Version ' DB VERS/10+'0','.',(VERS MOD 10)+'0',0 LDA FCB+1 ; GET FIRST CHAR OF FILE NAME CPI ' ' ; NO FILE SPEC? JZ HELP CPI '/' ; OPTION CAUGHT? JNZ ECONT ; PRINT HELP INFORMATION HELP: CALL PRINT DB CR,LF,'Syntax:' DB CR,LF,' PROTECT dir:filename.typ,dir:fn.ft,... o...' DB CR,LF,'Options:' DB CR,LF,' C -- Control Mode (Allow user to set each file)' DB CR,LF,' I -- Inspect Mode (Give user option to set att)' DB CR,LF,' n -- 1 <= n <= 8; Set Tag Attribute' DB CR,LF,' A -- Set AR (Archive) Attribute' DB CR,LF,' R -- Set R/O Attribute (no R sets R/W)' DB CR,LF,' S -- Set SYS Attribute (no S sets Non-System)' DB CR,LF DB 0 ; RETURN TO OS RETURN: LHLD STACK ; GET OLD STACK SPHL ; SET IT RET ; COPY BUFFER INTO TEMP BUFFER ECONT: LHLD CMDLNE ; PT TO CMDLNE BUFFER XCHG LXI H,BUFF+1 ; PT TO BUFFER MVI B,80H ; ARBITRARY CALL MOVEB ; COPY INTO COMMAND LINE BUFFER ; EXTRACT FLAGS IF PRESENT XRA A ; SET NO INSPECT, NO R/O, NO ARCH, AND NO SYSTEM FILES STA INSPECT STA READONLY STA SYSTEM STA ARCHIVE STA CONTROL ; SET NO CONTROL MODE MVI B,8 ; CLEAR TAG BITS LXI H,TAGS CALL FILLB LXI H,0 ; SET FILE COUNT SHLD FILECNT LHLD CMDLNE ; PT TO BUFFER ; SKIP TO FILE NAME STRING SBLANK: MOV A,M ; SKIP TO NON-BLANK CPI ' ' ; ? JNZ SBL1 INX H ; PT TO NEXT CHAR JMP SBLANK ; SKIP TO END OF FILE NAME STRING SBL1: MOV A,M ; SKIP TO OR EOL ORA A ; DONE? JZ OPT CPI ' ' ; JZ OPT INX H ; PT TO NEXT JMP SBL1 ; CHECK FOR LEADING SLASH ON OPTION AND SKIP IT IF SO OPT: CPI '/' ; OPTION CHAR? JNZ OPTION INX H ; SKIP SLASH ; PROCESS LIST OF OPTIONS OPTION: MOV A,M ; GET BYTE ORA A ; DONE? JZ DSPEC INX H ; PT TO NEXT CHAR CPI ' ' ; SKIP OVER SPACES JZ OPTION CPI '/' ; IF OPTION LETTER, OBVIOUS ERROR, SO HELP JZ HELP CPI '1' ; DIGIT? JC HELP CPI '8'+1 ; IN RANGE? JC OPTNUM CPI 'C' ; CONTROL? JZ OPTCTRL CPI 'I' ; INSPECT? JZ OPTINS CPI 'A' ; ARCHIVE JZ OPTAR CPI 'R' ; READ/ONLY? JZ OPTRO CPI 'S' ; SYSTEM FILES? JNZ HELP MVI A,80H ; SET FOR SYS FILES STA SYSTEM JMP OPTION OPTNUM: SUI '1' ; ADJUST '1' TO '8' TO 0-7 PUSH H ; SAVE PTR MOV E,A ; VALUE IN DE MVI D,0 LXI H,TAGS ; PT TO TAG BUFFER DAD D ; PT TO ELEMENT MVI M,80H ; SELECT ELEMENT POP H ; GET PTR TO NEXT CHAR JMP OPTION OPTCTRL: MVI A,0FFH ; CONTROL MODE STA CONTROL JMP OPTION OPTINS: MVI A,0FFH ; INSPECT STA INSPECT JMP OPTION OPTAR: MVI A,80H ; SET ARCHIVE STA ARCHIVE JMP OPTION OPTRO: MVI A,80H ; SET R/O STA READONLY JMP OPTION ; EXTRACT DISK, USER, AND FILE NAME INFORMATION DSPEC: LHLD CMDLNE ; PT TO BEFORE FIRST BYTE DCX H DSPEC0: INX H ; PT TO BYTE MOV A,M ; GET BYTE ORA A ; DONE? JZ HELP CPI ' ' ; ? JZ DSPEC0 ; ; MAJOR REENTRY POINT WHEN FILE SPECS ARE SEPARATED BY COMMAS ; HL PTS TO FIRST BYTE OF NEXT FILE SPEC ; DSPEC1: CALL GETUD ; RESET USER IF NECESSARY LXI D,FCB ; PT TO FCB IN DE, PT TO FIRST CHAR OF FILE NAME IN HL MVI A,0 ; DIR BEFORE DU CALL ZFNAME ; EXTRACT FILE NAME INTO FCB, AND GET DISK AND USER SHLD NEXTCH ; SAVE PTR TO DELIMITER WHICH ENDED SCAN LXI D,FCB ; PT TO FCB CALL Z3LOG ; LOG INTO DU ; LOAD DIRECTORY AND PROTECT FILES PROT: LHLD DIRBUF ; PT TO END OF CODE MVI A,0C0H ; SELECT NON-SYS AND SYS FILES LXI D,FCB ; PT TO FCB CALL DIRQ ; LOAD DIR, SELECT FILES, PACK, AND ALPHABETIZE ; PROT DIR FILES; HL PTS TO FIRST FILE, BC=FILE COUNT CALL PROTFILES ; CHECK FOR NEXT FILE SPEC LHLD NEXTCH ; GET PTR MOV A,M ; GET DELIM CPI ',' ; ANOTHER FILE? JNZ PROTDONE INX H ; PT TO CHAR AFTER COMMA JMP DSPEC1 ; CONTINUE PROCESSING ; PROT COMPLETE -- PRINT COUNT AND EXIT PROTDONE: CALL PRCOUNT ; PRINT FILE COUNT JMP RETURN ; PROT SELECTED FILES PROTFILES: MOV A,B ; CHECK FOR ANY FILES LOADED ORA C RZ ; PRINT FILE NAME PROTLP: PUSH B ; SAVE ENTRY COUNT CALL CRLF ; NEW LINE PUSH H ; SAVE PTR TO FCB INX H ; PT TO FILE NAME MVI B,8 ; PRINT NAME CALL PRNT MVI A,'.' ; DECIMAL CALL COUT MVI B,3 ; PRINT TYPE CALL PRNT POP H ; GET PTR ; CHECK FOR CONTROL MODE AND PERFORM CONTROL FUNCTION IF SET LDA CONTROL ; GET FLAG ORA A ; NZ=YES JNZ PROTCTRL ; CHECK FOR INSPECTION AND INSPECT IF SET LDA INSPECT ; GET FLAG ORA A ; 0=NO JZ DOIT ; PROMPT USER FOR PROTECT CALL PROTQ ; PROT QUESTION CPI 'Q' ; QUIT? JZ QUIT CPI 'Y' ; YES? JZ DOIT ; DON'T PROTECT FILE NODO: CALL PRINT DB ' ++ NO Attribute Change ++',0 JMP PROTTEST ; PROMPT USER FOR PROT PROTQ: CALL PRINT ; PRINT PROMPT DB ' -- Protect (Y/N/Q=Quit/other=N)? ',0 CALL CIN ; GET RESPONSE CALL CAPS ; CAPITALIZE CALL COUT ; ECHO RET ; CONTROL FUNCTION -- ALLOW USER TO SET BITS AS HE DESIRES PROTCTRL: PUSH H ; SAVE PTR TO FILE XRA A ; A=0 STA READONLY ; CLEAR R/O, SYS, ARCHIVE, AND TAGS STA SYSTEM STA ARCHIVE LXI H,TAGS MVI B,8 CALL FILLB CALL PRINT DB ' -- Attributes (? for Help)? ',0 MVI A,0FFH ; CAPITALIZE CALL BBLINE ; INPUT LINE FROM USER CALL CRLF ; NEW LINE MVI B,80H ; MSB SET PCTRL: MOV A,M ; GET ATTRIBUTE FLAG ORA A ; DONE? JZ PDOIT ; DO PROTECTION THEN INX H ; PT TO NEXT CPI ' ' ; SKIP JZ PCTRL CPI 'Q' ; QUIT? JZ QUIT CPI 'A' ; ARCHIVE? JZ PCTRLA CPI 'S' ; SYSTEM? JZ PCTRLS CPI 'R' ; R/O? JZ PCTRLR CPI '1' ; DIGIT? JC PCTRLH ; HELP IF NOT CPI '8'+1 ; RANGE? JC PCTRLN ; DO NUMBER PCTRLH: CALL PRINT DB CR,LF,' Attributes may be specified as follows --' DB CR,LF,' A = Archive, R = R/O, S = SYS, 1-8 = Tags' DB CR,LF,' The command Q exits' DB CR,LF,0 POP H ; GET FCB PTR POP B ; GET ENTRY COUNT JMP PROTLP ; PROCESS AGAIN PCTRLA: MOV A,B ; GET FLAG STA ARCHIVE ; SET FLAG JMP PCTRL PCTRLS: MOV A,B ; GET FLAG STA SYSTEM ; SET FLAG JMP PCTRL PCTRLR: MOV A,B ; GET AND SET FLAG STA READONLY JMP PCTRL PCTRLN: PUSH H SUI '1' ; CONVERT TO OFFSET MOV E,A ; OFFSET IN DE MVI D,0 LXI H,TAGS ; SET TAG DAD D MOV M,B ; SET BIT POP H JMP PCTRL ; CONTINUE ; QUIT PROTECT PROGRAM QUIT: CALL PRCOUNT ; PRINT COUNT OF FILES PROTECTED CALL PRINT DB CR,LF,' QUIT',0 JMP RETURN ; PROT FILE, BUT GET PTR FIRST PDOIT: POP H ; GET PTR ; PROT FILE DOIT: PUSH H LXI D,PROTFCB ; COPY TARGET FILE INTO PROTECT'S FCB MVI B,16 ; 16 BYTES CALL MOVEB ; COPY LXI H,TAGS ; SET TAG BITS NOW INX D ; PT TO FIRST TAG BIT MVI B,8 ; 8 TAG BITS DOITL: LDAX D ; GET BYTE FROM PROT FCB ANI 7FH ; MASK OUT OLD MSB ORA M ; OR IN TAG BIT STAX D ; PUT BYTE BACK INX H ; PT TO NEXT INX D DCR B ; COUNT DOWN JNZ DOITL LDA READONLY ; GET R/O BIT MOV B,A ; SAVE IN B LDAX D ; GET BYTE ANI 7FH ; MASK OUT OLD MSB ORA B ; OR IN NEW MSB STAX D ; PUT IT BACK INX D ; PT TO SYS BIT LDA SYSTEM ; GET SYS BIT MOV B,A ; SAVE IT LDAX D ; GET BYTE ANI 7FH ; MASK OUT OLD MSB ORA B ; MASK IN NEW MSB STAX D ; PUT IT BACK INX D ; PT TO ARCHIVE BIT LDA ARCHIVE ; GET ARCHIVE BIT MOV B,A ; SAVE IT LDAX D ; GET BYTE ANI 7FH ; MASK OUT OLD MSB ORA B ; MASK IN NEW MSB STAX D ; PUT IT BACK LXI D,PROTFCB ; PT TO FCB CALL INITFCB ; INIT IT MVI C,30 ; SET FILE ATTRIBUTES CALL BDOS CALL PRINT DB ' Set to ',0 LXI H,PROTFCB+1 MVI B,8 ; 8 TAGS MVI C,'1' ; SET DIGIT PATTL1: MOV A,M ; GET BYTE ANI 80H ; PRINT ATT? JZ PATTL2 MOV A,C ; GET DIGIT CALL COUT PATTL2: INR C ; INCREMENT DIGIT INX H ; PT TO NEXT DCR B ; COUNT DOWN JNZ PATTL1 MOV A,M ; GET R/O BYTE ANI 80H ; MASK IT JZ PATTL3 CALL PRINT DB ' R/O ',0 JMP PATTL4 PATTL3: CALL PRINT DB ' R/W ',0 PATTL4: INX H ; PT TO SYS BYTE MOV A,M ; GET SYS BYTE ANI 80H ; MASK IT JZ PATTL5 CALL PRINT DB 'SYS',0 JMP PATTL6 PATTL5: CALL PRINT DB 'DIR',0 PATTL6: INX H ; PT TO ARCHIVE BYTE MOV A,M ; GET ARCH BYTE ANI 80H ; MASK IT JZ PATTL7 CALL PRINT DB ' AR',0 PATTL7: LHLD FILECNT ; INCREMENT FILE COUNT INX H SHLD FILECNT POP H ; GET PTR TO DIRECTORY ENTRY ; PT TO NEXT ENTRY PROTTEST: LXI D,ESIZE ; PT TO NEXT ENTRY DAD D POP B ; GET COUNT DCX B ; COUNT DOWN MOV A,B ; CHECK FOR ZERO ORA C JNZ PROTLP ; RETURN TO CALLER RET ; ; PRINT CHARS PTED TO BY HL FOR B BYTES ; PRNT: MOV A,M ; GET CHAR CALL COUT INX H ; PT TO NEXT DCR B ; COUNT DOWN JNZ PRNT RET ; ; PRINT COUNT OF NUMBER OF FILES PROTECTED ; PRCOUNT: CALL CRLF ; NEW LINE LHLD FILECNT ; GET COUNT MOV A,L ; CHECK FOR NONE ORA H JZ PRNO CALL PHLDC ; PRINT DECIMAL COUNT JMP PRMS PRNO: CALL PRINT DB 'No ',0 PRMS: LHLD FILECNT ; 1 FILE PROTECTED? MOV A,H ; HIGH ZERO? ORA A JNZ PRMULT MOV A,L ; LOW ONE? CPI 1 JZ PRSING PRMULT: CALL PRINT DB ' Files Protected',0 RET PRSING: CALL PRINT DB ' File Protected',0 RET ; ; BUFFERS ; INSPECT: DS 1 ; INSPECT FLAG (0=NO, 0FFH=YES) CONTROL: DS 1 ; CONTROL FLAG (0=NO, 0FFH=YES) ARCHIVE: DS 1 ; ARCHIVE FLAG (0=NO, 80H=YES) SYSTEM: DS 1 ; SYSTEM FLAG (0=NO, 80H=YES) READONLY: DS 1 ; READ/ONLY FLAG (0=NO, 80H=YES) TAGS: DS 8 ; 8 TAG BITS NEXTCH: DS 2 ; PTR TO NEXT CHAR IN MULTIFILE COMMAND LINE FILECNT: DS 2 ; COUNT OF NUMBER OF FILES PROTECTED PROTFCB: DS 40 ; FCB FOR PROTECT CMDLNE: DS 2 ; PTR TO COMMAND LINE SAVE AREA DIRBUF: DS 2 ; DIRECTORY BUFFER STACK: DS 2 ; OLD STACK PTR END