home *** CD-ROM | disk | FTP | other *** search
- PAGE 61,132
-
- TITLE DataPath 1.3 - Not Copyrighted (nc) 1987 - GDC Software
-
- COMMENT *
-
- DATAPATH.COM - This program attaches itself to MS-DOS or PC-DOS for
- automatic search of specified subdirectories or disks for
- a program's support ( help, overlay, etc.) files. It will
- support CP/M style calls ( CALL 0005h ) as well as normal
- MS-DOS calls. Detailed information on use and technical
- information is in the file DATAPATH.DOC.
-
-
- ASSEMBLY - MASM DATAPATH;
- LINK DATAPATH;
- EXE2BIN DATAPATH.EXE DATAPATH.COM
-
- AUTHOR - Bruce Dubbs
- GDC Software
- 122 Valencia Dr.
- Universal City, TX 78148
-
- THIS PROGRAM IS NOT COPYRIGHTED 1987. IT IS RELEASED INTO
- THE PUBLIC DOMAIN FOR WHATEVER USE YOU WANT. IF YOU WANT
- TO DISTRIBUTE THIS PROGRAM OR USE IT WITH ANY OTHER WAY,
- AN ACKNOWLEDGEMENT WOULD BE NICE. *
-
-
- SUBTTL Basic Definitions and Setup
- PAGE
-
- NUL EQU 00H
- LF EQU 0AH
- CR EQU 0DH
-
- TRUE EQU 0FFFFH
- FALSE EQU NOT TRUE
-
- .SALL ; Supress MACRO listings
-
- SUBTITLE MACRO STRING ; Change the subtitle but
- ; don't display SUBTTL command
- SUBTTL STRING
- .LIST
- PAGE
- ENDM
-
- PRINT MACRO STRING ; Print a string
- MOV DX,OFFSET STRING
- MOV AH,9
- INT 21H
- ENDM
-
-
- CSEG SEGMENT
-
- ASSUME CS:CSEG,DS:CSEG,SS:CSEG,ES:NOTHING
-
- ORG 0
- XFER_ADDRESS LABEL BYTE
-
- ORG 80H
- DP_LENGTH LABEL BYTE
-
- ORG 81H
- DATAPATH LABEL BYTE
-
- ORG 100H
-
- START: JMP INSTALL ; Jump to installation
- DW 64 DUP (?)
- STACK LABEL WORD
- WORK_AREA DB 128 DUP (?)
- ID DB 'DataPath 1.3' ; 1.3
-
- ;------------------------------------------------------------------------------
- .XLIST
- SUBTITLE <BDOS redirection module>
-
- BDOS PROC FAR
-
- ; In a program designed to run under CP/M, a CALL to location 5h would call
- ; BDOS. In MS-DOS, CP/M compatability is attempted by inserting a FAR CALL
- ; at location 5h. From there the first instruction found is a far jump. The
- ; function request was passed in register CL.
-
- ; This routine rearranges the stack, and sets up for a proper INT 21h function
- ; request.
-
- ; Note: CL = 0 (TERMINATE) must be handled specially because the CS segment
- ; is not compatable with a memory resident DataPath.
-
- CMP CL,0 ; Terminate?
- JNE BDOS_2
- JMP CS:BDOS_ADDR
- BDOS_2: POP AX ; Throw away 0Ah return addr
- POP AX ; Now swap the top two words on
- POP CS:BDOS_TEMP ; the stack
- PUSH AX
- PUSH CS:BDOS_TEMP
- MOV AH,CL ; Set the function
- INT 21H ; and go do it
- RET
-
- BDOS_TEMP DW ?
- BDOS_ADDR LABEL DWORD
- BDOS_OFFSET DW ?
- BDOS_SEGMENT DW ?
-
- BDOS ENDP
-
- ;------------------------------------------------------------------------------
- .XLIST
- SUBTITLE <Interrupt 24h (Abort) routine>
- ABORT PROC FAR
-
- ; This is the fatal error abort routine to check for open drive doors, etc.
- ; It will be used only when we are searching for a file. We will ignore
- ; any error and return to the program with carry set.
-
- POP AX ; Discard the INT 24H return
- POP AX ; address and flags
- POP AX
-
- POP AX ; Restore user registers
- POP BX
- POP CX
- POP DX
- POP SI
- POP DI
- POP BP
- POP DS
- POP ES
-
- XCHG BP,SP ; Set the carry flag on the
- OR BYTE PTR 4[BP],1 ; stack so it will be set
- XCHG BP,SP ; after the IRET
- IRET
-
- ABORT ENDP
-
- ;------------------------------------------------------------------------------
- PAGE
-
- ; The routines below set and restore the INT 24H fatal error handler.
- ; They use an INT 21H call that reenters DataPath. The stack will grow a
- ; little, but the call is just passed to MS-DOS.
-
- SET_ABORT: PUSH AX ; Save registers
- PUSH BX
- PUSH ES
- MOV AX,3524H ; Get INT 24H address
- INT 21H
- MOV ABORT_OFFSET,BX ; and save it
- MOV ABORT_SEGMENT,ES
- MOV DX,OFFSET ABORT
- MOV AX,2524H ; Set the interrupt address
- INT 21H
- POP ES ; Restore registers
- POP BX
- POP AX
- RET
-
- CLEAR_ABORT: PUSH AX ; Save registers
- PUSH DX
- PUSH DS
- LDS DX,ABORT_ADDRESS ; Reset address
- MOV AX,2524H ; Set the interrupt address
- INT 21H
- POP DS ; Restore registers
- POP DX
- POP AX
- RET
-
- ABORT_ADDRESS LABEL DWORD
- ABORT_OFFSET DW ?
- ABORT_SEGMENT DW ?
-
- ;------------------------------------------------------------------------------
- .XLIST
- SUBTITLE <Interrupt 21H intercept>
- ; When installed, DataPath intercepts all INT 21H call and works on three
- ; of them.
-
- NEW_21: PUSHF ; Save flags
- CMP AH,0FH ; Is the call 'OPEN' ?
- JE OPEN
- CMP AH,23H ; Is the call 'FILE SIZE' ?
- JE OPEN
- CMP AH,0BDH ; Is this 'our' function?
- JE OUR_FUNCTION
- CMP AH,3DH ; Is it 'OPEN FILE HANDLE' ?
- JNE OLD
- JMP HANDLE
-
- OLD: POPF ; Restore flags we called with
- JMP CS:OLD_21 ; Otherwise don't mess with the
- ; interrupt
-
- ; Check if caller is looking for DataPath
-
- OUR_FUNCTION: PUSH ES ; Save registers 1.2
- PUSH CX ; 1.2
- PUSH SI ; 1.2
- PUSH DI ; 1.2
-
- PUSH CS ; Set destination to us
- POP ES ;
- MOV DI,OFFSET ID ; Point to our ID 1.2
- MOV CX,12 ; 1.2
- REPE CMPSB ; See if ID is us 1.2
-
- POP DI ; Restore registers 1.2
- POP SI ; 1.2
- JCXZ ID_OK ; If zero, ID matches 1.2
- POP CX ; Reset registers 1.2
- POP ES ; 1.2
- JMP OLD ; And continue to DOS 1.2
-
- ID_OK: POP CX ; Reset CX 1.2
- ADD SP,2 ; ES stays the same 1.2
- NOT BX ; Invert BX to say we're here
- POPF
- IRET
-
-
- SAVE_SS DW ? ; Stack Segment storage
- SAVE_SP DW ? ; Stack Pointer storage
- OLD_21 LABEL DWORD ; Real INT 21H address
- OLD_21_OFFSET DW ?
- OLD_21_SEGMENT DW ?
- VERBOSE DB 0FFH ; TRUE
- WRITE_ENABLE DB 0 ; FALSE
- .XLIST
- SUBTITLE <INT 21H Functions 'OPEN' and 'FILE SIZE'>
-
- ; This procedure handles the old CP/M 'OPEN' routine. If the call does not
- ; directly, a call to the routine 'FIND_FILE' checks any alternate paths.
- ; If the file is then found, the directory is changed to the found file's
- ; directory, the file is opened, and the directory is then changed back to
- ; the original directory.
-
- FUNCTION DB ? ; Calling function
- DRIVE_SPECIFIED DB ?
- CURRENT_DRIVE DB ?
- RESULT DB ?
- FCB_OFFSET DW ?
- FCB_SEGMENT DW ?
- FILENAME DB 13 DUP (?)
- ; Flags are already pushed
- OPEN: STI ; Reenable interrupts
- MOV CS:FUNCTION,AH ; Save calling function
- CALL CS:OLD_21 ; Try to open the file
- CMP AL,0 ; Successful ?
- JNE OPEN_2 ; If not, try DataPath
- IRET ; Otherwise return
-
- ; Search the DataPath
-
- OPEN_2: MOV CS:SAVE_SS,SS ; Save the stack
- MOV CS:SAVE_SP,SP
- MOV AX,CS ; Set the stack
- MOV SS,AX
- MOV SP,OFFSET STACK
- PUSH BX ; Save the registers
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
- PAGE
-
- ; Set up defaults and save FCB data.
-
- MOV ES,AX ; Set string destination seg
- MOV SI,DX
- MOV CS:ATTRIBUTES,0 ; Set default attributes
- MOV CS:FCB_OFFSET,DX ; Save FCB address
- MOV CS:FCB_SEGMENT,DS
-
- CLD ; String increase
- LODSB ; Get 1st FCB char (bump SI)
- CMP AL,0FFH ; Extended FCB ?
- JNE OPEN_4
- MOV AL,5[SI] ; Get attributes
- MOV CS:ATTRIBUTES,AL ; and save
- MOV AL,6[SI] ; Get drive specification
- ADD SI,7 ; Adjust to point to filename
-
- ; Copy filename to a work area as an ASCII string. Also check for wildcards.
- ; If a wildcard is found, don't search DataPath.
-
- OPEN_4: MOV CS:DRIVE_SPECIFIED,AL; Save drive specification
-
- MOV CX,8
- MOV DI,OFFSET FILENAME ; Point to work area
-
- OPEN_5: LODSB ; Transfer filename
- CMP AL,'?'
- JE OPEN_8A
- CMP AL,' ' ; Blanks terminate the string
- JE OPEN_6
- STOSB
- OPEN_6: LOOP OPEN_5
-
- MOV AL,'.' ; Add a '.'
- STOSB
- MOV CL,3
-
- OPEN_7: LODSB ; Transfer extension to work
- CMP AL,'?' ; area
- JE OPEN_8A
- CMP AL,' '
- JE OPEN_8
- STOSB
- LOOP OPEN_7
-
- OPEN_8: MOV AL,NUL ; Terminate ASCIIZ string
- STOSB
- PAGE
-
- PUSH CS
- POP DS ; DS points to us
- MOV RESULT,0FFH ; Set default to not found
- MOV DX,OFFSET FILENAME ; ES:DX points to filename
- MOV DI,DX
- CALL GET_LENGTH
- CMP CL,0
- JE OPEN_8A
- CALL FIND_PATH
- JNC OPEN_9 ; File not found
-
- OPEN_8A: JMP OPEN_20
-
- ; We found the file. We will now:
- ; 1. Get the found drive.
- ; 2. Get the current directory on the found drive.
- ; 3. Set the found directory on the found drive.
- ; 4. Set found drive in FCB.
- ; 5. Open the file.
- ; 6. Reset the current directory on the found drive.
- ; 7. If the sspecified FCB drive was not zero, reset it.
-
- OPEN_9: MOV AH,19H ; Get current drive
- INT 21H
- INC AL ; Set 1=A, 2=B, etc
- MOV CURRENT_DRIVE,AL
-
- MOV DI,OFFSET XFER_ADDRESS ; Get found drive
- MOV BX,DX
- MOV AL,1[BX] ; Check if 2nd char is a ':'
- CMP AL,':' ; If drive not specified,
- JE OPEN_10 ; then get current drive
-
- MOV AL,CURRENT_DRIVE
- ADD AL,'@' ; Make ASCII
- JMP SHORT OPEN_11
-
- OPEN_10: MOV AL,[BX] ; Get found drive
- OPEN_11: MOV CL,AL ; Save in CL and
- STOSB ; memory
- MOV AX,'/:' ; Add ':/' (stored backward)
- STOSW
-
- MOV SI,DI ; Set up for 'Get Directory'
- SUB CL,'@' ; Make drive numeric
- MOV DL,CL ; Save in CL
- MOV AH,47H ; Get current directory
- INT 21H
- JC OPEN_20 ; Shouldn't happen
- PAGE
-
- MOV DI,END_PATH ; Point to filename
- DEC DI ; Point to end of path
- MOV AL,NUL ; Make ASCIIZ string
- STOSB
-
- MOV DX,BX ; Point to directory
- MOV AH,3BH
- INT 21H ; Set directory Path
-
- PUSH DS
- MOV DX,FCB_OFFSET ; Point to FCB
- MOV DS,FCB_SEGMENT
- MOV BX,DX
- MOV AL,[BX] ; Get 1st char
- CMP AL,0FFH ; Check for extended FCB
- JNE OPEN_14
- ADD BX,7 ; Point to drive specifier
- OPEN_14: MOV [BX],CL ; Set drive specifier
-
- MOV AH,CS:FUNCTION ; Now open the file
- PUSHF
- CALL CS:OLD_21
- POP DS
- MOV RESULT,AL ; Save result
-
- MOV DX,OFFSET XFER_ADDRESS
- MOV AH,3BH
- INT 21H ; Reset found directory
-
- MOV AL,DRIVE_SPECIFIED ; If drive was specified,
- CMP AL,0 ; reset it
- JNE OPEN_16
- MOV AL,CURRENT_DRIVE ; otherwise, use current drive
- OPEN_16: MOV BX,FCB_OFFSET ; Point to FCB
- MOV DS,FCB_SEGMENT
- MOV AH,[BX] ; Get 1st character
- CMP AH,0FFH ; Check for extended FCB
- JNE OPEN_18
- ADD BX,7 ; Point to drive
- OPEN_18: MOV [BX],AL ; Set drive
- PAGE
-
- OPEN_20: POP ES ; Restore all registers
- POP DS
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
-
- ; Note -- interrupts are automatically disabled for one instruction after
- ; updating a segment register
-
- MOV SS,CS:SAVE_SS
- MOV SP,CS:SAVE_SP
- MOV AH,CS:FUNCTION
- MOV AL,CS:RESULT ; Return result of OPEN
- IRET
-
- .XLIST
- SUBTITLE <INT 21H Function to 'OPEN FILE HANDLE'>
-
- ; This procedure handles the 'OPEN FILE HANDLE' routine. If the call does
- ; not work directly, a call to the routine 'FIND_FILE' checks any alternate
- ; paths. If the file is found, the file is then opened.
-
- HANDLE: CLI ; Enable hardware interrupts
- MOV CS:CALLER,AX ; Save calling function
- CALL CS:OLD_21 ; Try the open as sent
-
- JC HANDLE_0
- JMP HANDLE_4 ; Success
-
- ; Try data paths
- HANDLE_0: MOV CS:SAVE_AX,AX ; Save original error code
- MOV CS:SAVE_SS,SS ; Save old SS:SP
- MOV CS:SAVE_SP,SP
- MOV AX,CS
- MOV SS,AX ; SS <- CS
- MOV SP,OFFSET STACK ; Set stack pointer
- PUSH BX ; Save CPU state
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
-
- MOV BX,DS
- MOV DS,AX ; DS <- CS
- MOV ES,BX ; ES <- OLD DS
-
- PAGE
-
- ; See if the caller:
- ; 1. Asked for a open to write, or
- ; 2. Has a path length not in the range of 1..80 bytes, or
- ; 3. Had any wildcards in the file name, or
- ; 4. Specified a directory or drive.
- ; If any of the above are true, do not search extra paths.
-
-
- CMP WRITE_ENABLE,TRUE ; See if read only
- JE HANDLE_1 ; Skip next if so
-
- MOV AX,CALLER ; Get calling function
- CMP AL,0 ; Open for read?
- STC ; Set if error
- JNE HANDLE_3 ; If not, skip DataPath
-
- HANDLE_1: PUSH BX
- MOV BX,DX
- CMP ES:BYTE PTR[BX+1],':'; if drive is specified,
- JNE HANDLE_2 ; ignore it
- ADD DX,2
- HANDLE_2: MOV DI,DX ; Set DI for SCASB instructions
- POP BX
-
- CALL GET_LENGTH ; Get length of filename
- STC ; Set if error
- CMP CL,0 ; If zero, return
- JE HANDLE_3
-
- CALL CHECK_WILD ; Check for wildcard characters
- JC HANDLE_3 ; If present, return
-
- MOV ATTRIBUTES,0111B ; Match any attribute
- CALL FIND_PATH ; Search for the file
- JC HANDLE_3
-
- MOV AX,CALLER ; No error, open the file
- PUSHF
- CALL OLD_21
- JC HANDLE_3 ; Jump if we have an error
- MOV HANDLE_NUM,AX
-
- HANDLE_3: POP ES ; Restore all registers
- POP DS
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- MOV AX,CS:SAVE_AX ; This is original error code
- MOV SS,CS:SAVE_SS
- MOV SP,CS:SAVE_SP
- JC HANDLE_4
- MOV AX,CS:HANDLE_NUM ; If no error, return the handle
- PAGE
-
- ; Insure the flags on the stack are set properly.
-
- HANDLE_4: XCHG BP,SP ; We want to index on SP
- JC HANDLE_6
- AND BYTE PTR 4[BP],0FEH ; Clear carry on the stack
- JMP SHORT HANDLE_8 ; or
- HANDLE_6: OR BYTE PTR 4[BP],1 ; Set carry on stack
- HANDLE_8: XCHG BP,SP ; Reset registers
- IRET ; OK to return
-
- CALLER DW ?
- HANDLE_NUM DW ?
- SAVE_AX DW ?
- ;------------------------------------------------------------------------------
- .XLIST
- SUBTITLE <Subroutines>
-
- ; Find the length of the path
-
- GET_LENGTH: CLD ; Strings increase
- PUSH DI ; Save start location
- MOV AL,NUL
- MOV CX,80 ; Set max length of path
- REPNE SCASB ; Find a NUL
- SUB CX,79 ; Get length of path
- NEG CX
- MOV CS:NAME_LENGTH,CX ; Save the filename length
- POP DI
- RET
- ;------------------------------------------------------------------------------
-
- ; Check for Drive, Directory, or wildcards ( ':', '\', '*', or '?' )
-
- CHECK_WILD: MOV BX,OFFSET WILDCARDS ; Point to exceptions
- MOV CX,4 ; There are 4 of them
-
- C1: PUSH CX ; Save the count
- PUSH DI ; Save the start location
- MOV CX,NAME_LENGTH ; Length to scan
- MOV AL,[BX] ; Get a character
- REPNE SCASB ; See if its there
- CMP CL,0 ; Set the flags
- POP DI ; Reset start location
- POP CX ; Reset count
- JNE C2 ; Found exception, no DataPath
- INC BX ; else, point to next char
- LOOP C1 ; and check for it
- CLC
- RET ; Return OK
-
- C2: STC ; Error return
- RET
-
- NAME_LENGTH DW ?
- WILDCARDS DB ':\*?'
- ;------------------------------------------------------------------------------
- PAGE
-
- ; The subroutine FIND_PATH checks for the file in question along the
- ; supplementary DataPath. The logic of the routine is as follows:
-
- ; 1. If the DataPath is exhausted, exit with carry set.
- ; 2. Copy the next DataPath, delimited by a ';' to the working area.
- ; a. Insure it ends with a backslash.
- ; 3. Execute DOS call to 'Find First Matching File'.
- ; a. If file is found, return with DS:DX pointing to the
- ; path/filename for a subsequent Open call.
- ; b. Otherwise, goto step 1 above.
-
- ; Upon entry, ES:DX points to filename.
-
- ATTRIBUTES DB ?
- END_PATH DW ?
- FILE_OFFSET DW ?
- FILE_SEGMENT DW ?
- LAST_PATH DB ?
-
- FIND_PATH PROC NEAR
- MOV FILE_OFFSET,DX ; Save file pointers
- MOV FILE_SEGMENT,ES
-
- CALL SET_ABORT ; Set our INT 24H handler
- CALL SET_DTA ; Set Disk Transfer Address
-
- MOV SI,OFFSET DATAPATH ; Point to DataPath
-
- ; Move the path to our work area
-
- MOV AX,CS ; Reset destination to us
- MOV ES,AX
- MOV LAST_PATH,FALSE ; Not at last path yet
-
- F1: CMP LAST_PATH,TRUE ; Are we done?
- JNE F2 ; Continue if done
- CALL CLEAR_ABORT ; All done, reset system
- CALL RESET_DTA
- STC ; Set carry means not found
- RET
-
- F2: MOV CX,LENGTH WORK_AREA ; Point to work area
- MOV DI,OFFSET WORK_AREA
- MOV AX,NUL ; Start AX as two nuls
-
- PAGE
-
- F3: LODSB ; Get a character
- CMP AL,';' ; End of path?
- JE F6
- CMP AL,'$' ; End of path and DataPath?
- JE F5
- STOSB ; Save the character in memory
- MOV AH,AL ; and here to check for '\'
- LOOP F3 ; Get next character
-
- F5: MOV LAST_PATH,TRUE ; Set last path flag
- F6: CMP AH,NUL ; Check for zero length DataPath
- JE F7
- MOV AL,'\' ; Is last character a backslash
- CMP AH,AL
- JE F7
- STOSB ; If not, make it a backslash
-
- ; Add the filename to the path
-
- F7: MOV END_PATH,DI ; Save pointer to path end
- PUSH DS
- PUSH SI
- MOV SI,FILE_OFFSET
- MOV CX,NAME_LENGTH ; Set the length
- MOV DS,FILE_SEGMENT ; Point to original filename
- REP MOVSB ; Transfer filename
- MOVSB ; Including the NUL
- POP SI
- POP DS
-
- ; Find First Matching File
-
- MOV DX,OFFSET WORK_AREA
- MOV AH,4EH ; Find first
- MOV CH,0
- MOV CL,ATTRIBUTES ; Match given attributes
- INT 21H ; Find the file
- JC F1 ; If not found, check next path
-
- CALL CLEAR_ABORT ; Successful return
- CALL RESET_DTA
- CLC
- RET
- FIND_PATH ENDP
- ;------------------------------------------------------------------------------
-
- PAGE
-
- ; Set Disk Transfer Address
-
- SET_DTA: MOV AH,2FH ; Save the old Disk Xfer Addr
- INT 21H
- MOV DTA_OFFSET,BX
- MOV DTA_SEGMENT,ES
- MOV AH,1AH ; Set our Disk Xfer Addr
- MOV DX,OFFSET XFER_ADDRESS
- INT 21H
- RET
-
- ; Reset Disk Transfer Address
-
- RESET_DTA: PUSH DS
- PUSH DX
- LDS DX,DTA ; Point to old Disk Xfer Addr
- MOV AH,1AH
- INT 21H ; Reset it
- POP DX
- POP DS
- RET
-
- DTA LABEL DWORD
- DTA_OFFSET DW ?
- DTA_SEGMENT DW ?
- ;------------------------------------------------------------------------------
- .XLIST
- SUBTITLE <DataPath installation procedure>
-
- ; Start of DataPath installation procedure
-
- TRANSIENT LABEL WORD ; Start of transient load
-
- BAD_DOS_MSG DB 'DataPath requires DOS 2.0 or above',CR,LF
- DB 'DataPath NOT installed',CR,LF,'$'
- RESIDENT_FLAG DB 0 ; False 1.2
- HELP DB 0 ; False 1.2
- PAGE
-
- INSTALL: MOV AX,CS
- MOV DS,AX ; INSURE DS IS SET
-
- ; Check for DOS 2.0 or above
-
- MOV AH,30H ; Get DOS version
- INT 21H
- CMP AL,2 ; Is it 2.0 or more?
- JGE INSTALL_1 ; Continue if OK
-
- PRINT BAD_DOS_MSG
- INT 20H ; TERMINATE
-
- INSTALL_1: MOV AX,3521H ; GET OLD INT 21 ADDR
- INT 21H
- MOV OLD_21_OFFSET,BX ; SAVE IT
- MOV OLD_21_SEGMENT,ES
-
- ; Check if DataPath is already installed by calling a special (our own)
- ; function of INT 21H.
-
- MOV AH,0BDH ; Our interrupt
- MOV SI,OFFSET ID ; Point to name 1.2
- XOR BX,BX ; Insure BX is zero
- INT 21H ; See if DataPath is there
- INC BX ; If so, BX will now be zero
- JNZ INSTALL_3
-
- ; DataPath is already there
-
- MOV RESIDENT_FLAG,TRUE
- JMP SHORT INSTALL_4
-
- ; Set new interrupt 21 address
-
- INSTALL_3: MOV DX,OFFSET NEW_21 ; POINT TO OFFSET
- MOV AX,2521H ; UPDATE THE INTERRUPT
- INT 21H
- PAGE
- ; Set the CP/M BDOS Entry Point for compatability
-
- MOV BX,6
- LES BX,[BX] ; GET ADDRESS OF CALL TO CP/M
- MOV AX,ES:1[BX] ; AND SAVE IT
- MOV BDOS_OFFSET,AX
- MOV AX,ES:3[BX]
- MOV BDOS_SEGMENT,AX
-
- MOV DX,OFFSET BDOS
- MOV ES:1[BX],DX ; SET OUR ADDRESS INTO MS-DOS
- MOV ES:3[BX],DS
-
- ; If DataPath program is not resident OR a new DataPath is passed, then
- ; transfer the new Datapath
-
- INSTALL_4: CALL CHECK_SWITCHES
- CMP RESIDENT_FLAG,FALSE
- JE INSTALL_5
- CMP DP_LENGTH,0
- JE INSTALL_6
- INSTALL_5: CALL SET_DATAPATH
-
- ; If a new DataPath is not passed, or we are in VERBOSE mode, display the
- ; current DataPath
-
- CMP HELP,TRUE ; Always display if help 1.2
- JE INSTALL_6 ; is set 1.2
- CMP ES:VERBOSE,TRUE
- JE INSTALL_6
- CMP DP_LENGTH,0
- JNE INSTALL_8
- INSTALL_6: CALL DISPLAY
-
- ; Just terminate if we are already resident
-
- INSTALL_8: CMP CS:RESIDENT_FLAG,TRUE
- JNE INSTALL_9
- MOV AX,4C00H ; OK RETURN
- INT 21H ; TERMINATE
-
- ; Exit but stay resident - set paragraphs to save
-
- PARAS = ((TRANSIENT-XFER_ADDRESS) SHR 4) + 1 ; 1.2
-
- INSTALL_9: MOV DX,PARAS ; SET LENGTH TO RESERVE 1.2
- MOV AX,3100H
- INT 21H ; TERMINATE & STAY RESIDENT
-
- PAGE
-
- ; Transfer the DataPath but do some pre-processing
-
- SET_DATAPATH: CMP RESIDENT_FLAG,TRUE ; IF RESIDENT THEN ES WAS SET
- JE SET_2 ; BY INT 21H FUNCTION 'BD'h
- PUSH CS ; ELSE SET TO CS
- POP ES
- CMP HELP,TRUE ; IF HELP AND NOT RESIDENT, 1.2
- JE SET_9 ; SET NULL DATAPATH 1.2
-
- SET_2: CLD ; INCREMENT STRINGS
- CMP HELP,TRUE ; IF HELP SET, DON'T RESET 1.2
- JE SET_10 ; DATAPATH 1.2
- MOV SI,OFFSET DATAPATH ; POINT TO SOURCE CS:81
- MOV DI,SI ; POINT TO DEST ES:81
- MOV CL,DP_LENGTH ; GET LENGTH OF PASSED STRING
- CMP CL,0 ; IF LENGTH IS 0, STORE NUL
- JE SET_9 ; STRING
- MOV CH,0
-
- SET_4: LODSB ; GET A CHARACTER
- CMP AL,' ' ; THROW AWAY NON PRINTING
- JBE SET_8 ; CHARACTERS
- CMP AL,'z' ; AND OTHER WEIRD CHARS
- JA SET_8
- CALL CHECK_ILLEGAL ; CHECK FOR ILLEGAL PATHNAME 1.3
- JC SET_8 ; 1.3
- CMP AL,'a' ; CONVERT CHARS TO UPPER CASE
- JB SET_7
- AND AL,0DFH
- SET_7: STOSB ; SAVE THE CHARACTER
- SET_8: LOOP SET_4
- SET_9: MOV AL,'$' ; STORE A TERMINATING $
- STOSB
- SET_10: RET
-
- CHECK_ILLEGAL PROC NEAR ; 1.3
- PUSH CX ; SAVE REGISTERS 1.3
- PUSH DI ; 1.3
- PUSH ES ; 1.3
- PUSH CS ; SET ES=CS 1.3
- POP ES ; 1.3
- MOV CX,10 ; CHECK 10 CHARACTERS 1.3
- MOV DI,OFFSET ILLEGAL_CHARS ; 1.3
- REPNE SCASB ; SEE IF WE HAVE ILLEGAL 1.3
- CLC ; ASSUME CHAR OK 1.3
- JNE CHECK_ILLEGAL_1 ; JUMP IF NO MATCHES 1.3
- STC ; CHAR IS ILLEGAL 1.3
- CHECK_ILLEGAL_1: POP ES ; RESTORE REGISTERS 1.3
- POP DI ; 1.3
- POP CX ; 1.3
- RET ; 1.3
- CHECK_ILLEGAL ENDP ; 1.3
-
- ILLEGAL_CHARS DB '$"[]*?+=<>' ; 1.3
-
- .XLIST
- SUBTITLE <Display Subroutine>
-
- ; This procedure outputs DataPath info to the screen
-
- DISPLAY PROC NEAR
-
- PRINT INFO ; Print heading
- CMP RESIDENT_FLAG,TRUE ; If first time say installed
- JE DISPLAY_1
- PRINT INSTALLED
-
- DISPLAY_1: PRINT CRLF
- PRINT NC ; Print our name
- PRINT CRLF2 ; Skip a line
- PRINT VERBOSE_MSG ; Print verbose status
- CMP ES:VERBOSE,TRUE
- JE DISPLAY_2
- PRINT OFF
- JMP SHORT DISPLAY_3
- DISPLAY_2: PRINT ON
-
- DISPLAY_3: PRINT WRITE_ACCESS ; Print open for write status
- CMP ES:WRITE_ENABLE,TRUE
- JE DISPLAY_4
- PRINT OFF
- JMP SHORT DISPLAY_5
- DISPLAY_4: PRINT ON
-
- DISPLAY_5: PRINT CRLF ; Skip a line
-
- PRINT DATAPATH_MSG ; Tell the current DataPath
-
- PUSH DS
- PUSH ES
- POP DS ; POINT TO DATAPATH
- PRINT DATAPATH
- POP DS
-
- PRINT CRLF2
- CMP HELP,TRUE ; 1.2
- JNE DISPLAY_6 ; 1.2
- PRINT USAGE ; 1.2
-
- DISPLAY_6: RET
-
- DISPLAY ENDP
- PAGE
-
- INFO DB 'DataPath version 1.3 $' ; 1.3
- INSTALLED DB 'Installed$'
- NC DB '(nc) 1987 by GDC Software$'
- VERBOSE_MSG DB 'Verbose mode is $'
- WRITE_ACCESS DB 'Write access is $'
- ON DB 'on',CR,LF,'$' ; 1.2
- OFF DB 'off',CR,LF,'$' ; 1.2
- DATAPATH_MSG DB 'Current DataPath=$'
- CRLF2 DB CR,LF
- CRLF DB CR,LF,'$'
- USAGE DB 'DataPath usage:',CR,LF
- DB ' DataPath path1 [;path2...] [/V] [/Q] [/R] [/W]'
- DB ' [/H]',CR,LF
- DB ' where path1, path2... are the paths to '
- DB 'search for files',CR,LF
- DB ' /V sets verbose mode [default]',CR,LF
- DB ' /Q sets quiet mode',CR,LF
- DB ' /R sets read only mode [default]',CR,LF
- DB ' /W allows opens for writing',CR,LF
- DB ' /H writes this message',CR,LF,'$'
-
- .XLIST
- SUBTITLE <Check Switches Subroutine>
- ; This procedure checks for a /W, /R, /V, and /Q and sets the VERBOSE and
- ; WRITE_ENABLE flags accordingly.
-
- CHECK_SWITCHES PROC NEAR
-
- CMP RESIDENT_FLAG,TRUE ; If resident ES is set to
- JE SWITCH_1 ; resident portion of DataPath
- PUSH CS ; otherwise use CS
- POP ES
-
- SWITCH_1: CLD ; Scan for a '/'
- MOV AL,'/'
- XOR CX,CX
- MOV CL,DP_LENGTH
- MOV DI,OFFSET DATAPATH
- PUSH ES
- PUSH DS ; Set ES to point to us
- POP ES
- REPNZ SCASB
- POP ES ; Restore ES
- JCXZ SWITCH_9 ; All done -- return
-
- MOV AL,[DI] ; Get the character after the /
- AND AL,0DFH ; Make upper case
- MOV WORD PTR[DI-1],' ' ; Blank out /x
-
- CMP AL,'V' ; /V --> set VERBOSE
- JNE SWITCH_2
- MOV ES:VERBOSE,TRUE
- JMP SHORT SWITCH_1
-
- SWITCH_2: CMP AL,'Q' ; /Q --> clear VERBOSE
- JNE SWITCH_3
- MOV ES:VERBOSE,FALSE
- JMP SHORT SWITCH_1
-
- SWITCH_3: CMP AL,'R' ; /R --> Only work on files
- JNE SWITCH_4 ; opened to read
- MOV ES:WRITE_ENABLE,FALSE
- JMP SHORT SWITCH_1
-
- SWITCH_4: CMP AL,'W' ; /W --> Work on files for
- JNE SWITCH_5 ; read or write
- MOV ES:WRITE_ENABLE,TRUE
- JMP SHORT SWITCH_1
-
- SWITCH_5: CMP AL,'H' ; /H --> Type usage message 1.2
- JNE SWITCH_1
- MOV HELP,TRUE
- JMP SHORT SWITCH_1
-
- SWITCH_9: RET
-
- CHECK_SWITCHES ENDP
-
- CSEG ENDS
- END START