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