Files
DR-DOS-OpenDOS/COMMAND/CSUP.ASM
2020-11-04 23:59:28 +01:00

757 lines
16 KiB
NASM

; File : $Workfile: CSUP.ASM$
;
; Description :
;
; Original Author : DIGITAL RESEARCH
;
; Last Edited By : $CALDERA$
;
;-----------------------------------------------------------------------;
; Copyright Work of Caldera, Inc. All Rights Reserved.
;
; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
; CIVIL LIABILITY.
;-----------------------------------------------------------------------;
;
; *** Current Edit History ***
; *** End of Current Edit History ***
;
; $Log$
; ENDLOG
;
; 28 Jan 88 Change the validation check for the environment. Now we look
; for a valid DOS Memory Descriptor which is owned by the
; Command Processor.
; 12 May 88 Handle Empty environments correctly (Thanks DesqView)
; 26 May 88 ach _stack is only defined for MSC
; 16 Jun 88 Support TURBO C Stack checking and enable CHKSTK for
; MSC only.
; 26 Aug 88 Make the Minimum Stack Address Public
; 14 Apr 89 Make heap_top public
; 14 Jul 89 Move findeof to assembler
; 09 Oct 90 Write heap_size() to return remaining bytes on heap at
; any given instance
;
_DLS_INCLS_ equ 1
include message.def
CGROUP GROUP _TEXT
DGROUP GROUP _DATA
codeOFFSET equ offset CGROUP:
dataOFFSET equ offset DGROUP:
STACKSLOP equ 128 ; Minimum Stack Size
jmps macro label ; Define a Macro to generate the
jmp SHORT label ; Short Jmp instruction
endm
_TEXT SEGMENT byte public 'CODE'
ifdef MWC
extrn longjmp:near ; MetaWare does not preceed library
LONGJUMP equ longjmp ; functions with an UNDERSCORE
else
ifdef WATCOMC
extrn longjmp_:near
LONGJUMP equ longjmp_
else
extrn _longjmp:near
LONGJUMP equ _longjmp
endif
endif
assume cs:CGROUP, ds:DGROUP, es:nothing
public _debug
_debug proc near
out 0fdh,al
ret
_debug endp
; Environment manipulation routines
; =================================
;
;BOOLEAN env_entry(BYTE *buf, WORD entry);
;
; Copy entry number ENTRY into the buffer BUF. Return FAILURE
; if ENTRY cannot be found.
;
assume cs:CGROUP, ds:DGROUP, es:nothing
public _env_entry
_env_entry PROC near
cld
push bp
mov bp,sp
push ds
push si
push es
push di
call get_env ; Get the environment segment
mov es,bx ; Initialise ES
mov cx,ax ; Check the environment size - 1
dec cx ; and FFFF bytes if no env header
xor di,di ; Offset to start scaning for data
xor ax,ax
env_e10:
cmp es:byte ptr [di],al ; Is this a Null string
jz env_fail ; Then hit the end of the search
cmp word ptr 06[bp],0 ; Is this the entry required
jz env_e20
repnz scasb ; Scan for the next zero byte
jcxz env_fail ; and abort if out of space
dec word ptr 06[bp] ; Decrement the string count
jmps env_e10
env_e20: ; Found the correct entry now copy
mov si,di ; Get the correct source offset
push ds
push es
pop ds
pop es
mov di,04[bp]
env_e30:
lodsb
stosb ; Copy byte through AL
or al,al
jnz env_e30 ; and check for end of string
jmps env_exit
_env_entry ENDP
;BOOLEAN env_scan(BYTE *key, BYTE *buf);
;
; Scan through the environment searching for the string KEY then copy
; the result into buffer.
Public _env_scan
_env_scan PROC near
cld
push bp
mov bp,sp
push ds
push si
push es
push di
call get_env ; Get the environment segment
call get_key ; Find the key
jz env_fail ; Abort if an error occurs
add di,dx ; Add the Key length and just copy
mov si,di ; The key definition into the
push ds ; Buffer
push es
pop ds
pop es
mov di,06[bp]
env_s10:
lodsb
stosb ; Copy byte through AL
or al,al
jnz env_s10 ; and check for end of string
jmps env_exit
_env_scan ENDP
;
; Environment handling exit routines
env_err: ; Invalid Environment descriptor
mov ax,-1 ; return with -1
jmps env_ret
env_fail: ; Environment fail the operation
mov ax,1 ; requested has failed.
jmps env_ret
env_exit:
xor ax,ax
env_ret PROC near
pop di
pop es
pop si
pop ds
pop bp
ret
env_ret ENDP
;
;BOOLEAN env_del(BYTE *key);
; Delete the entry matching KEY from the environment and return
; success or failure
;
public _env_del
_env_del PROC near
cld
push bp
mov bp,sp
push ds
push si
push es
push di
call get_env ; Get the environment segment
jz env_err ; Stop if not the real thing
call get_key ; Find the key
jz env_fail ; Abort if an error occurs
mov ds,bx ; Point DS at the environment
mov si,di ; save the destination offset
add di,dx ; and search for the end of this string
xor ax,ax
mov cx,-1
repnz scasb ; Now search for the end of string
xchg si,di ; Swap the source and destination
env_d10:
cmp al,[si] ; Is this the end of the environment
jz env_d20 ; Yes so terminate
env_d15:
lodsb
stosb ; Copy through AL checking for the end
or al,al
jnz env_d15 ; of the environment after each
jmps env_d10 ; end of string.
env_d20:
stosw ; Force 0 word to be placed here to
jmps env_exit ; terminate the string
_env_del ENDP
;BOOLEAN env_ins(BYTE *str);
; Insert the string at the end of the current environment
; checking if there is enough room to save the string.
;
public _env_ins
_env_ins PROC near
cld
push bp
mov bp,sp
push ds
push si
push es
push di
call get_env ; Get the environment segment
jz env_err ; and its segment
sub ax,2 ; Decrement the size of the env
mov cx,ax ; to make sure we can store a 0
xor ax,ax ; word terminator
mov es,bx ; Find the end of the current env
xor di,di
env_i10:
repnz scasb
jcxz env_fail
cmp al,es:byte ptr [di]
jnz env_i10
cmp di,1 ; Is this an empty Environment
jnz env_i25 ; No. If yes then start from offset 0
dec di
env_i25:
mov bx,di ; Save the starting address of string
mov si,04[bp] ; Get the source string offset
env_i20:
lodsb
stosb ; Copy the String until a zero byte
or al,al ; then add the environment terminator
loopnz env_i20
mov es:word ptr [di],0
jz env_exit ; Exit with no error if the string is
mov es:byte ptr [bx],00 ; terminated correctly otherwise remove
jmps env_fail ; all traces of this string and exit
_env_ins ENDP
;
page
;
; Returns environment size in Bytes in AX or zero if error
; and BX is the Environment segment.
;
get_env PROC near
push es
mov dx,__psp ; Get the Current PSP in DX
mov es,dx ; and point ES at Our PSP
xor ax,ax ; and assume an error condition
mov bx,es:002Ch ; get environment segment
dec bx ; Check for memory descriptor
mov es,bx
inc bx
cmp es:byte ptr 00h,'M' ; Byte 0 must contains either an
jz get_e10 ; M or Z and the DMD be owned by
cmp es:byte ptr 00h,'Z' ; the Command Processor
jnz get_e20
get_e10:
if 0
cmp dx,es:word ptr 1h ; Is this "OUR" PSP if not then
jnz get_e20 ; complain bitterly.
endif
mov ax,es:word ptr 3h ; Get the memory size in paragraphs
shl ax,1 ; convert to size in bytes and exit.
shl ax,1
shl ax,1
shl ax,1
get_e20:
pop es
or ax,ax
ret
get_env ENDP
;
; enter this search function with BX == ENVIRONMENT SEGMENT
; 04[bp] == Key string offset
; On exit AX == 0 Failure
; else DX is Key string Length
; DI is Offset
;
get_key PROC near
push ds
pop es ; Calculate the length of the
mov di,04[bp] ; key by scaning the string for
mov al,0 ; a zero byte.
mov cx,-1
repnz scasb
neg cx ; CX is the length of the sting + 2
sub cx,2
mov dx,cx ; Save the count in dx
xor ax,ax
mov es,bx ; Point ES at the environment
xor di,di ; and start from the begining
get_k10:
push di ; Save incase this is a match
mov cx,dx ; Get the string length
mov si,04[bp] ; and offset and check for a match
repz cmpsb
jnz get_k20 ; No match so get the next string
pop di ; This is the starting offset
or ax,-1 ; All ok
ret
get_k20:
pop cx ; Throw away the old DI
mov cx,-1 ; Set the count to maximum
repnz scasb ; and search for the end of the string
cmp al,es:[di] ; exit with error if this is the end
jnz get_k10 ; of the environment
ret
get_key ENDP
page
assume cs:CGROUP, ds:DGROUP, es:nothing
ifdef MSC
;
;
; STACK(WORD) allocates memory from the C STACK if at any stage
; the stack grows to within STACKSLOP of the top of the heap this
; function executes a LONGJUMP using the BREAK_ENV buffer. This will
; terminate any internal function.
;
PUBLIC _stack
_stack:
pop bx ; Get the return address
pop cx ; and the number of bytes required
add cx,1 ; Force CX to be a even value to
and cx,not 1 ; ensure the stack is word aligned
mov ax,sp ; Get the Stack
sub ax,STACKSLOP ; Include STACKSLOP
sub ax,cx ; Subtract requested buffer
jc heap_error ; Exit with error if Carry
cmp ax,heap_top ; Are we still above the heap
jc heap_error ; No
pop ax ; Get possible saved SI
pop dx ; Get possible saved DI
push dx ; Restore the stack to its
push ax ; origibnal format
sub sp,cx ; All OK so update SP
push dx ; Save possible saved DI
push ax ; Save possible saved SI
mov ax,sp ; Return pointer
add ax,4 ; Adjust pointer for saved SI/DI
push cx ; Restore the entry parameter
jmp bx ; and return to the caller
endif
;
; HEAP_GET(WORD) allocates memory from the C HEAP if at any stage
; the heap grows to within STACKSLOP of the base of the stack this
; function executes a LONGJUMP using the BREAK_ENV buffer. This will
; terminate any internal function.
;
PUBLIC _heap_get
_heap_get:
push bp
mov bp,sp
mov ax,heap_top
add ax,04[bp] ; Add in the requested value
jc heap_error ; Exit with error if Carry
sub bp,STACKSLOP ; now check that the stack
cmp bp,ax ; is still well above the
jc heap_error ; heap.
mov stack_min,ax ; Update the Stack Minimum Variable
add stack_min,STACKSLOP ; for the CHKSTK routine
xchg ax,heap_top ; Return the existing heap top
pop bp ; and update the local variable
ret ; with the new value.
heap_error:
mov dx,3 ; Return the Heap Overflow error
push dx
mov ax,dataOFFSET _break_env ; using the JMP_BUF
push ax
call LONGJUMP ; We are never coming back
;
; HEAP_SIZE returns the size remaining on the C HEAP
;
PUBLIC _heap_size
_heap_size:
push bp
mov bp,sp
mov ax,heap_top
add ax,STACKSLOP
sub bp,ax
jnc noprobs
xor bp,bp
noprobs:
mov ax,sp
pop bp
ret
;
; HEAP() can only return a pointer to the top of the C Heap
; and is identical in function to HEAP_GET(0) except that no
; overflow checking is required and the calling overhead is
; minimal.
;
PUBLIC _heap
_heap:
mov ax,heap_top
ifndef FINAL
ifdef WATCOMC
add ax,STACKSLOP ; we'd better do some stack checking
cmp ax,sp ; 'cause the C isn't doing it now
jae heap_error
sub ax,STACKSLOP
endif
endif
ret
;
; VOID HEAP_SET(BYTE *) forces the heap to a specified value
;
PUBLIC _heap_set
_heap_set:
push bp
mov bp,sp
mov ax,04[bp] ; Get the new value for the HEAP
cmp ax,dataOFFSET _end ; base and check against the
jnb heap_s10 ; absolute base. If below then force
mov ax,dataOFFSET _end ; the heap to the absolute base
heap_s10:
mov heap_top,ax
mov stack_min,ax
add stack_min,STACKSLOP
pop bp
ret
page
ifdef MSC
;
; This is our own Stack Check routine which is called on
; entry to every C routine. AX contains the number of bytes
; to be reseved on the stack.
;
PUBLIC __chkstk
__chkstk:
pop cx ; Get the Return Address
mov bx,sp ; Calculate the new SP value
sub bx,ax ; AX contains the number of bytes
jc OVERFLOW@ ; to reserve.
cmp bx,stack_min ; Check we are still above the heap
jc OVERFLOW@ ; No !!! Help
mov sp,bx ; Update the Stack pointer
jmp cx ; Its Ok lets go back
endif
ifdef WATCOMC
Public __STK
__STK:
cmp ax,sp
jnb OVERFLOW@
sub ax,sp
neg ax
cmp ax,stack_min
jbe OVERFLOW@
ret
endif
ifdef TURBOC
Public OVERFLOW@ ; Public TURBOC Stack Error Handler
endif
OVERFLOW@:
mov dx,2 ; Return the STACK Overflow error
push dx
mov ax,dataOFFSET _break_env ; using the JMP_BUF
push ax
call LONGJUMP ; We are never coming back
; MLOCAL UWORD CDECL findeof(s, count) /* find ^Z in buffer */
; BYTE FAR *s; /* buffer to search */
; UWORD count; /* # of bytes in buffer */
; {
; REG UWORD i;
;
; i = count;
; while(i) { /* Scan through the data */
; if(*s++ == (BYTE) 0x1A) /* looking for a Control-Z */
; break;
; i--;
; }
;
; return (count - i);
; }
PUBLIC _findeof
_findeof:
push bp ; establish a stack frame
mov bp,sp ; s dword 04[bp]
push es ; count word 08[bp]
push di ; save important registers
cld
les di,4[bp] ; load up the pointer
mov cx,8[bp] ; and the count
mov al,26 ; looking for EOF mark in the buffer
repne scasb ; scan until we find one
jne findeof10 ; if we do find one
inc cx ; then include it in the count
findeof10:
mov ax,8[bp] ; we wanted this many
sub ax,cx ; subtract any past EOF
pop di
pop es
pop bp
ret
ifdef DLS
public _my_dls_init
; void my_dls_init()
;extrn _dls_init:near
;extrn _dls_get_table:near
_my_dls_init proc far
push ds
push cs
pop ds
call _dls_init
mov ax,1
push ax
call _dls_get_table
pop ax
pop ds
ret
_my_dls_init endp
public _copy_crit_msgs
_copy_crit_msgs proc near
extrn _crit_msgs:word
extrn _crit_text:byte
push ds
push es
push di
push si
push ds
pop es
push cs
pop ds
mov si,_dls_table
add si,msg0
mov si,[si]
mov di,offset DGROUP:_crit_text
add di,2
mov bx,offset DGROUP:_crit_msgs
add bx,2
mov cx,24
ccm_loop1:
mov es:[bx],di
add bx,2
ccm_loop2:
lodsb
stosb
cmp al,'$'
jne ccm_loop2
loop ccm_loop1
pop si
pop di
pop es
pop ds
ret
_copy_crit_msgs endp
public _copy_rld_msgs
_copy_rld_msgs proc near
extrn _rld_msgs:word
extrn _rld_text:byte
push ds
push es
push di
push si
push ds
pop es
push cs
pop ds
mov si,_dls_table
add si,reload_msgs
mov si,[si]
mov di,offset DGROUP:_rld_text
add di,2
mov bx,offset DGROUP:_rld_msgs
add bx,2
mov cx,3
crm_loop1:
mov es:[bx],di
add bx,2
crm_loop2:
lodsb
stosb
cmp al,0
jne crm_loop2
loop crm_loop1
pop si
pop di
pop es
pop ds
ret
_copy_rld_msgs endp
public _dls_msg1
; char *dls_msg1(int)
_dls_msg1:
push bp
mov bp,sp
push bx
mov ax,4[bp]
shl ax,1
mov bx,cs:_dls_table
add bx,ax
mov ax,cs:[bx]
pop bx
pop bp
ret
endif ; ifdef DLS
public _dos_parse_filename
_dos_parse_filename proc near
push bp
mov bp,sp
sub sp,30h
push es
push ds
pop es
lea di,-30h[bp]
mov si,4[bp]
mov ax,2901h
int 21h
mov ah,0
pop es
add sp,30h
pop bp
ret
_dos_parse_filename endp
public _flush_cache
_flush_cache proc near
push si
push di
push bp
mov ax,4a10h
mov bx,0
mov cx,0edch
int 2fh
cmp ax,6756h ; NWCACHE
je do_flush
cmp ax,0BABEh ; SmartDrive
jne skip_flush
do_flush:
mov ax,4a10h
mov bx,1
mov cx,0edch
int 2fh
skip_flush:
pop bp
pop di
pop si
ret
_flush_cache endp
_TEXT ENDS
page
_DATA SEGMENT byte public 'DATA'
extrn __psp:word
extrn _end:byte
extrn _break_env:word
extrn low_seg:word
public stack_min
public heap_top
ifdef TURBOC
public ___brklvl ; Turbo C does an inline check against
___brklvl label word ; ___brklvl and id SP < ___brklvl then
endif ; it calls OVERFLOW@
stack_min dw dataOFFSET _end + STACKSLOP
heap_top dw dataOFFSET _end ; Current Top of Heap
_DATA ENDS
END