Metropoli BBS
VIEWER: spawnpth.asm MODE: TEXT (ASCII)
	NAME	spawnpth
	TITLE	Path search for disk-swapping spawn() by Ralf Brown
	PAGE	60,132
;-----------------------------------
; (c) Copyright 1990, 1991, 1992 Ralf Brown  All Rights Reserved
; This code may be redistributed as a part of the complete SPAWNO package,
; under its distribution conditions.
;-----------------------------------
;  SPAWNO v4.10
;
;  assembler defines:
;   __TINY__, __SMALL__, __COMPACT__, __MEDIUM__, __LARGE__, __HUGE__
;	exactly one of the above must be defined to specify the memory
;	model in use
;-----------------------------------

__BSS__ equ 1				; yes, we are using uninitialized storage
	INCLUDE RULES.ASI

	Header@				; set up segment and group definitions

; bit flags for the extensions which were found
COM_EXT equ 1
EXE_EXT equ 2
USER_EXT equ 4

;-----------------------------------------------------------
; initialized data

DSeg@
IFNDEF __TP	; defined in BSeg@ if __TP
ExtSym@ _psp,WORD,__CDECL__
ENDIF

PATH_EQUALS db 'PATH='
PATH_EQUALS_LEN equ $-PATH_EQUALS
DSegEnd@

;-----------------------------------------------------------
; uninitialized data

BSeg@
IFDEF __TP
ExtSym@ _psp, WORD, __CDECL__
ENDIF

env		dd ?

extrn ___SPAWN_PNAME:byte
executable_path equ ___SPAWN_PNAME
executable_pad	equ ___SPAWN_PNAME + 80

BSegEnd@

CSeg@
	ASSUME	DS:DGROUP

extrn __SPAWN_ERRNO:near
extrn __SPAWN_DDSEP:near
extrn __SPAWN_CHECK_DIR:near

;----------------------------------------------------------------
; char * pascal __spawn_search(const char *name) ;
;    given a program name, search the PATH for it, returning the full pathname
;    or NULL if not found
;----------------------------------------------------------------
PubProc@ __SPAWN_SEARCH,__PASCAL__
; parameters
 @name = DPTR_ [bp+2+cPtrSize]
; start of subroutine
	ASSUME	DS:DGROUP,ES:NOTHING
	push	bp
	mov	bp,sp
IFDEF __HUGE__
	push	ds			; save caller's DS
	mov	ax,DGROUP		;   and establish addressing to our
	mov	ds,ax			;   data segment
ENDIF ;__HUGE__
	push	es
	push	di
	push	si
; set up pointer to environment
IFDEF __TINY__
	mov	es,ds:[002Ch]
ELSE
	mov	es,_psp@
	mov	es,es:[002Ch]
ENDIF ;__TINY__
	xor	di,di
	jmp short find_path
find_path_loop:
	mov	al,0
	cmp	byte ptr es:[di],al
	je	found_path
	cld
find_path_loop2:
	scasb				; find terminating zero
	jne	find_path_loop2
find_path:
	mov	cx,PATH_EQUALS_LEN
	mov	si,offset DGROUP:PATH_EQUALS
	repe	cmpsb
	jne	find_path_loop
found_path:
	mov	word ptr env+2,es
	mov	word ptr env,di
	mov	byte ptr ___SPAWN_PNAME,0  ; start with null path
search_loop:
IF LDATA
	push	word ptr @name+2
ENDIF
	push	word ptr @name
	call	__SPAWN_CHECK_DIR
	jnz	search_successful
	or	al,al			; was there a pathspec in the name?
	jne	search_failed	     ; don't look at PATH unless simple filename
	les	bx,env
	ASSUME	ES:NOTHING
	cmp	byte ptr es:[bx],0
	je	search_failed
	mov	di,offset DGROUP:executable_path
dir_copy_loop:
	mov	al,es:[bx]
	or	al,al
	je	dir_copy_done
	inc	bx
	cmp	al,';'			; separator for path entries
	je	dir_copy_done
	mov	[di],al
	inc	di
	cmp	di,offset DGROUP:executable_pad	  ; make sure we don't overrun buf
	jb	dir_copy_loop
dir_copy_done:
	mov	al,[di-1]
	call	__spawn_ddsep		; was last char a slash/backslash/colon?
	je	dir_has_slash
	mov	byte ptr [di],'\'
	inc	di
dir_has_slash:
	mov	byte ptr [di],0
	mov	word ptr env,bx
	jmp	search_loop

search_successful:
	mov	ax,bx
IF LDATA
	mov	dx,ds
ENDIF
	jmp short search_done
search_failed:
	mov	ax,2			; file not found
	call	__SPAWN_ERRNO
	xor	ax,ax
IF LDATA
	xor	dx,dx
ENDIF
search_done:
	pop	si
	pop	di
	pop	es
IFDEF __HUGE__
	pop	ds
ENDIF ;__HUGE__
	pop	bp
	ret	dPtrSize
EndProc@ __SPAWN_SEARCH,__PASCAL__

CSegEnd@
	END
[ RETURN TO DIRECTORY ]