www.pudn.com > drdossrc.zip > CSUP.ASM


;    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