;**********************************************************
;
; USRDFLT2.CCP by R. L. Plouffe
; (703) 527-3215
; June 4, 1981
;
; For CP/M 2.x systems only.
;
; Changed the code that restricts access to
; USER areas in order to take advantage of
; routines already in the CCP. Reduces the
; code that must be placed in your customiz-
; ed bios considerably...........RLP 6/4/81
;
; Originally written 5/26/81. This has been
; re-written to clean it up and to add labels
; and comments so it can be easily read.
; ...............................RLP 5/31/81
;
;These routines are based on ideas and code found on the
;CALAMITY CLIFFS machine. Authors are apparently Ron Fowler
;and Keith Peterson. What is done here is to integrate these
;ideas and to add two important new features. First a new
;kind of CCP command is added that is a pseudo CCP transient.
;These commands reside on disk as a transient, but may be called
;from any user area and any logged drive as long as they reside
;on drive A and in a pre-designated USER area. Second, the newly
;defined pseudo CCP/transients as well as existing (or additional)
;CCP commands may be defined as either public or private with
;private commands being accessible only after becoming password
;privileged. It should be apparent that among other things, these
;integrated routines avoid the necessity of placing copies of
;transient routines that are included in the pseudo definition
;in multiple USER areas. Certainly a must for PIP at least.
;Add this code to your customized user or BIOS file and the
;CCP patches will be automatically overlayed when you put it
;in with DDT provided that your file contains an equate for
;the CCP beginning address for your system size. NOTE that the
;command address table and the command strings have been taken
;out of the CCP. However, the code space that they occupied has
;been well stuffed with other patch code. An 18 byte spare area
;at the end of the BDOS is also used. Make sure that your version
;has this spare area still available and has not been used by some-
;ones customization. If it has, then place the code at the label
;BRIDGE into your customized BIOS.
;Donated for the benefit of hobby computing. This creation
;may not be sold.
;
;
CCP EQU YOUR CCP ADDRESS ;BASE OF CCP
;
BDOS EQU CCP+800H ;BASE OF BDOS
BIOS EQU CCP+1600H ;BASE OF BIOS
DFCB EQU 5CH ;ADDR OF DEFAULT FILE CNTRL BLK
DRIVE EQU 04H ;LOC OF CURRENT DRIVE BYTE
CR EQU 0DH
LF EQU 0AH
;
LENCMD EQU 5 ;LENGTH OF CCP CMD STRINGS
MAXUSER EQU 4 ;FOR EXAMPLE
BUFSIZE EQU CCP+6H ;LOC OF SIZE BYTE FOR CCP BUF
BDOSFNC EQU BDOS+6H ;BDOS FUNCTION
GETUSR EQU CCP+113H ;GET USER #
SETUSR EQU CCP+115H ;SET USER #
TSTUSR EQU CCP+692H ;TEST USER #
USRSAV EQU CCP+118H
CCPPASS EQU CCP+7EH ;LOCATION OF CCP PASSWORD
UPATCH0 EQU CCP+390H
UPATCH1 EQU CCP+393H
HUH EQU CCP+209H ;CCP HUH RESPONSE
CRLF EQU CCP+98H ;CCP CR/LF FUNCTION
RETCCP EQU CCP+382H ;RE-ENTRY TO CCP
CMDPTR EQU CCP+3B5H ;POINTER TO COMMAND ADDR TBL
STRPTR EQU CCP+32FH ;POINTER TO CCP CMD STRINGS
CMDCNT EQU CCP+335H ;BYTE VALUE = # OF COMMANDS
CMDLEN EQU CCP+33BH ;BYTE VALUE = LENGTH OF EACH
;COMMAND STRING.
TSTOPN EQU CCP+6DCH ;TEST FILE OPEN FUNCTION
CMDDRV EQU CCP+7F0H ;BYTE INDICATES DRV IN CMD
CMDERR EQU CCP+76BH ;HUH RESPONSE IF DR #
XTNSN EQU CCP+7D6H ;STORAGE LOC FOR FILE TYPE,
;EXT #, AND RECORD COUNT
RELOOK EQU CCP+6CDH ;RELOOK W/INDICATED DRIVE
TPASUB EQU CCP+75DH ;LOC TO SUSTITUTE BEFORE
;CALLING THE TPA
CONTINUE EQU CCP+75FH ;TO CONTINUE AFTER CALL TO TPA
GETRANS EQU CCP+6A5H ;GET TRANS OR CCP COMMAND
ERA EQU CCP+51FH ;ADDR OF ERA ROUTINE
REN EQU CCP+610H ;ADDR OF REN ROUTINE
SAVE EQU CCP+5ADH ;ADDR OF SAVE ROUTINE
DIR EQU CCP+477H ;ADDR OF DIR ROUTINE
TYPE EQU CCP+55DH ;ADDR OF TYPE ROUTINE
USER EQU CCP+68EH ;ADDR OF USER ROUTINE
TPA EQU 100H ;OR YOUR TPA ADDRESS
CCPSPARE EQU CCP+7F2H ;14 SPARE BYTES AT END OF CCP
BDOSPARE EQU BDOS+0DEEH ;18 SPARE BYTES AT END OF BDOS
;Addresses of holes left in CCP that are filled in
;with patches for transient user defaults
HOLE1 EQU CCP+310H ;EXACTLY 24 BYTES HERE
HOLE2 EQU CCP+3C1H ; " 6 " "
HOLE3 EQU CCP+3C7H ; " 8 " "
;
;**********************************************************
; BEGINNING OF CODE THAT IS PATCHED INTO THE CCP
;**********************************************************
;This is the CCP password to obtain privilege to higher USER
;areas and privileged CCP or transient commands. The password
;itself is ORGed at the very end of the CCP command buffer.
;The buffer is resized to permit this location. The advantage
;to this ORG is that any attempt to find it with DDT will be
;unsuccessful since DDT overlays the CCP, so this is an added
;measure of security. If you lengthen the password, reduce the
;value of the CCPPASS equate for each additional character in the
;password. Password may be mixed upper and lower case characters.
;
ORG CCPPASS
PASSWD: DB 'URPASSWRD',CR
ORG BUFSIZE
DB 75H ;10 bytes less than original
;
;The CCP-included command 'PASS' routine is at CKCCPAS which
;is located in your customized BIOS.
;**********************************************************
; This patch is used to restrict access to the higher user
; areas while leaving the lower user areas public. The high-
; est available public user area is defined by MAXUSER.
;
ORG USRSAV
DW SAVUSR ;ADDR TO JMP TO SO THAT
;CALLING USER NUMBER IS RE-
;TURNED TO AFTER EXECUTING
;A TRANSIENT
;The routines are located in your customized BIOS.
;**********************************************************
; This patch causes user number to be reported at the cp/m
; prompt.....i.e. - A2>. User 0 report is suppressed.
;
ORG UPATCH0
MVI C,USRFNC ;VALUE FOR USER FNC CALL
ORG UPATCH1
DW UPATCH ;ADDR OF PATCH TO CALL
;the routine UPATCH is located in the USER area of your
;customized BIOS
;**********************************************************
; This patch causes the CCP of a cp/m 2.x system to look on
; drive A when you are logged into a drive other than A and
; call for a .COM file that does not exist on that drive.
; Giving an explicit drive reference overrides this feature,
; so that you can always force the file to be loaded from a
; specific drive.
;
ORG TSTOPN
DW APATCH ;REPLACES 'CMDERR'
;
ORG CCPSPARE
APATCH: LXI H,CMDDRV ;GET DRIVE FROM CURRENT CMD.
ORA M ;FETCHES DRIVE
JNZ CMDERR ;GIVE ERROR IF CMD HAS DRIVE #
INR M ;FORCE TO DRIVE A
LXI D,XTNSN ;UNDO WHEN...
JMP RELOOK ;REENTERING CCP
;
;**********************************************************
;This patch extends the CCP to include up to N additional
;commands that are user defined. The commands may be either
;CCP-included or transient, and may be either private or
;public depending on password privilege.
;
ORG CMDPTR
CMDPTR: DW CMDTBL2 ;COMMAND TABLE ADDRESS (PUBLIC)
;
ORG STRPTR
STRPTR: DW CMDSTR2 ;COMMAND STRING ADDRESS (PUBLIC)
;
ORG CMDCNT
CMDCNT: DB (GETRAN0-CMDTBL2)/2 ;TO LIMIT PUBLIC ACCESS TO CCP
;COMMANDS. RESET TO ALL WHEN
;PASSWORD IS ENTERED FOR USER
;AREAS ABOVE MAXUSER.
ORG CMDLEN
CMDLEN: DB LENCMD ;LENGTH OF CCP COMMAND STRINGS
;The rest of this patch is in the USER area of your customized
;BIOS.
;
;**********************************************************
;This is the routine that cause those utilities which are in
;the CCP command table to be available from all user areas.
;They must be resident in USER 0 or 15 and named the same as in
;command string....i.e, 'EDIT' for 'WORDSTAR', 'STAT' for 'STAT',
;etc.. The names and addresses can be in either the public or
;private areas. Don't expand this code except to use indicated
;spare bytes because you will wipe out other good code if you
;do.
;
ORG HOLE2
TRDFLT0:
MVI E,0 ;VALUE FOR PUBLIC TRANSIENTS
PUSH D ;SAVE IT ON THE STACK
JMP DFLT ;TO DEFAULT TO USER VALUE
ORG HOLE1
TRDFLT15:
MVI E,15 ;VALUE FOR PRIVATE TRANSIENTS
PUSH D ;SAVE IT ON THE STACK
DFLT:
CALL GETUSR ;GET CALLING USER #
STA HOLDUSER ;SAVE IT
POP D ;GET DEFAULT USER VALUE IN E
CALL SETUSR ;SET THE USER # IN BDOS
LXI H,RSTUSR ;PUT ADDR OF RTNE IN HL
SHLD TPASUB ;SET TO CALL IT INSTEAD OF TPA
JMP GETRANS ;GET THE FILE TO THE TPA
DB 0,0 ;SPARE BYTES
;
ORG HOLE3
RSTUSR: LDA HOLDUSER ;GET THE SAVED USER #
MOV E,A ;PUT IT IN E
JMP BRIDGE
HOLDUSER:
DB 0
ORG BDOSPARE ;SPARE BYTES HERE IN BDOS
BRIDGE: CALL SETUSR ;SET USER #
LXI H,TPA ;PUT ADDR OF TPA IN HL
SHLD TPASUB ;SET TO CALL TPA NEXT TIME
CALL TPA ;DO IT NOW
JMP CONTINUE ;BACK TO CCP IN-LINE CODE
DB 0,0,0 ;SPARES
;
; END OF CODE THAT IS PATCHED INTO THE CCP (AND BDOS)
; *****
;
;**********************************************************
; BEGINNING OF CODE THAT IS PUT IN YOUR BIOS.
; SEE GENESYS AND GENEUSER FOR A TECHNIQUE TO
; EXPAND YOUR USER AREA.
;**********************************************************
ORG BIOS+WHATEVER
;This is the command string which is divided into private
;and public sections. Do not use more than five letters for
;the name of any command or transient and fill out each string
;to exactly five characters by using spaces below. Each string
;must occur at 5 character intervals. If you wish to use some
;other string length such as 4 as in the original CCP, just
;change the string lengths below and change the LENCMD equate
;from 5 to 4. I use 5 below so that MODEM can fit.
;
CMDSTR1:
DB 'ERA REN SAVE STAT PIP DDT ASM LOAD COPY EDIT '
CMDSTR2:
DB 'SRD DIR TYPE USER PASS MODEMBYE CRCK '
;
;**********************************************************
;This is the command address table which is divided into
;private and public areas. The address of the routine to be
;jumped to must be here for any CCP-included code as well as
;any that you add and put in your customized BIOS. For private
;and public transients, use TRDFLT15 AND TRDFLT0 respectively
;and put private transients in USER 15 on your system disk (A).
;Similarly, put public transients in USER 0 on 'A'. These trans-
;ients will now be available from any drive and from any USER #
;depending on password privilege. You can expand the table to
;any extent that you have space and the command string above
;must be expanded in synchronism.
;
;Put the private transients in USER 15
CMDTBL1:
DW ERA ;ERA....PRIVATE COMMANDS
DW REN ;REN
DW SAVE ;SAVE
DW TRDFLT15 ;STAT...THE FOLLOWING UTILITIES
DW TRDFLT15 ;PIP....WILL BE TREATED AS CCP
DW TRDFLT15 ;DDT....COMMANDS. THEY MUST BE ON
DW TRDFLT15 ;ASM....DISK AS TRANSIENTS AT USER 15
DW TRDFLT15 ;LOAD...AND WILL NOW BE AVAILABLE AT
DW TRDFLT15 ;COPY...ALL USER #'S
DW TRDFLT15 ;EDIT (RENAME WORDSTAR TO EDIT),
;or whatever your favorite editor is.
;Put the public transients below in USER 0
CMDTBL2:
DW TRDFLT0 ;SRD ....PUBLIC COMMANDS
DW DIR ;DIR
DW TYPE ;TYPE
DW USER0 ;USER
DW CKCCPAS ;PASS(WORD)
DW TRDFLT0 ;MODEM for Ward's MODEM program.
;I use this command for either
;XMODEM or MODEM7 depending on
;which one I have on drive A.
DW TRDFLT0 ;BYE for Ward's BYE program
DW TRDFLT0 ;CRCK does a CRC 16 check on file
GETRAN0: ;This must be last entry in table.
DW GETRANS ;Get the transient and execute or
;return to CCP w/HUH message if not
;on disk.
;
;**********************************************************
;This patch which is called from the CCP provides for a
;report of USER number at the prompt....i.e. A2> for USER 2,
;'A' drive.
;
UPATCH: LDA PASSFLG ;GET PASSWORD FLAG
INR A ;SEE IF SET
JNZ UPATCH2 ;SKIP IF NOT
LXI H,CMDSTR1 ;SET CMDSTRING POINTER TO
;BEGINNING OF ALL COMMANDS
SHLD STRPTR ;STORE IT IN STRING POINTER
LXI H,CMDTBL1 ;SET CMDTABLE POINTER TO
;BEGINNING OF ALL CMD ADDRESSES
SHLD CMDPTR ;STORE IT IN COMMAND TABLE POINTER
MVI A,(GETRAN0-CMDTBL1)/2 ;CALC # OF COMMANDS
STA CMDCNT ;STORE VAL IN SCAN ROUTINE IN CCP
UPATCH2:
CALL GETUSR ;GET USER NUMBER
ANI 0FH ;KILL UNWANTED BITS
JZ UPA2 ;IF USER 0, DON'T REPORT
CPI 10
JC UPA1 ;JIF USER NUM = 0 THRU 9
SUI 10 ;USER NUM = 10 THRU 15
PUSH PSW
MVI E,'1'
MVI C,CONSOUT ;VAL FOR CONSOLE OUT FNC
CALL BDOSFNC ;PRINT A '1'
POP PSW
;
UPA1: ADI '0'
MOV E,A
MVI C,CONSOUT ;VAL FOR CONSOLE OUT FNC
CALL BDOSFNC ;PRINT DIGIT
;
UPA2: MVI E,'>'
MVI C,CONSOUT ;VAL FOR CONSOLE OUT FUNCTION
JMP BDOSFNC ;PRINT '>', EXIT
;
;**********************************************************
;These are the routines which provide for limited USER area
;access. USER0 is jumped to before jumping from the CCP com-
;and parser to the CCP-included USER routine. SAVUSR is jumped
;to whenever resetting the user code and guarantees that the
;same user area will be returned to as was in effect before
;executing a transient command.
;
USER0: LDA PASSFLG ;SEE IF PRIVILEGED
INR A ;YES?
JZ USER ;TO USER CODE IF SO
MVI A,MAXUSER+1 ;RESTRICT ACCESS
STA TSTUSR ;DO IT HERE
JMP USER ;GOTO CCP USER CODE
;
SAVUSR: MOV A,E ;SEE IF GET OR SET USER
CPI 0FFH ;IS IT GET USER?
JZ BDOSFNC
MOV A,E ;GET USER #
RLC
RLC
RLC
RLC ;MOVE TO UPPER NIBBLE
MOV B,A ;SAVE REQUESTED USER #
LDA DRIVE ;GET CURRENT USER/DRIVE
ANI 0FH ;STRIP OFF OLD USER #
ORA B ;GET NEW USER #
STA DRIVE ;SET NEW USER #
JMP BDOSFNC ;SET IT AND EXIT
;
PASSFLG:
DB 0 ;STORE FOR PASSWORD FLAG
CKCCPAS:
LXI H,PASSWD ;POINT TO PASSWORD
CKPASS: LDA PASSFLG ;GET PASSWORD FLAG
INR A ;SEE IF SET
JZ RETCCP ;IF SO, RET TO CCP
CALL CRLF ;DO A CR/LF
MVI D,0 ;NO MISSED LETTERS
PWMLP: PUSH D
PUSH H
PWMLP1: MVI C,DIRCONIO ;GET A CHAR
MVI E,0FFH ;SET TO CONSOLE IN
CALL BDOSFNC ;DO IT
ORA A ;SEE IF CHAR ENTERED
JZ PWMLP1 ;LOOP IF NOT
POP H
POP D
CMP M ;MATCH PASSWORD?
JZ PWMAT ;..YES
MVI D,1 ;..NO, SHOW MISS
CPI CR
JNZ PWMLP ;..NO, WAIT FOR C/R
JMP HUH ;RETURN TO CCP WITH A HUH
;
PWMAT:
INX H
CPI CR ;SEE IF END OF PASSWORD
JNZ PWMLP ;GET ANOTHER CHAR IF NOT
MOV A,D ;ERROR INDICATOR TO A
ORA A ;ERROR?
JNZ HUH ;IF SO, SAY HUH
MVI A,0FFH ;VAL FOR PASSWORD FLAG
STA PASSFLG ;SET IT
MVI A,16 ;RESTORE
STA TSTUSR ;ALL USER AREAS
JMP RETCCP ;AND RETURN TO CCP
;
;
;BDOS FUNCTION CALL EQUATES
;
CONSOUT EQU 2 ;CONSOLE OUTPUT
DIRCONIO EQU 6 ;DIRECT CONSOLE INPUT OUTPUT
USRFNC EQU 32 ;USER FUNCTION CODE
;
; the
END
; for now