home *** CD-ROM | disk | FTP | other *** search
- NAME spawnpth
- TITLE Path search for disk-swapping spawn() by Ralf Brown
- PAGE 60,132
- ;-----------------------------------
- ; (c) Copyright 1990 Ralf Brown All Rights Reserved
- ; This code may be redistributed provided that:
- ; 1) this copyright notice remains intact and any changes are clearly
- ; marked
- ; 2) no fee of any kind is charged
- ;-----------------------------------
- ; assembler defines:
- ; __TINY__, __SMALL__, __COMPACT__, __MEDIUM__, __LARGE__
- ; exactly one of the above must be defined to specify the memory
- ; model in use
- ;-----------------------------------
-
- IFDEF __HUGE__
- %error Huge model not supported
- ENDIF ;__HUGE__
-
- __BSS__ equ 1 ; yes, we are using uninitialized storage
- INCLUDE RULES.ASI
-
- Header@ ; set up segment and group definitions
-
- FFBLK struc
- ?ffb_reserved db 21 dup (?)
- ?ffb_attr db ?
- ?ffb_time dw ?
- ?ffb_date dw ?
- ?ffb_size dd ?
- ?ffb_name db 13 dup (?)
- FFBLK ends
-
- ; bit flags for the extensions which were found
- COM_EXT equ 1
- EXE_EXT equ 2
- USER_EXT equ 4
-
- DSeg@
- ExtSym@ _psp,WORD,__CDECL__
- ExtSym@ _doserrno,WORD,__CDECL__
- DSegEnd@
-
- BSeg@
- env dd ?
-
- found_ext db ? ; which extensions have we found?
-
- executable_path db 80 dup (?) ; size of longest legal path+file+NUL
- executable_pad db 4 dup (?) ; in case we run over while adding extension
-
- ffb ffblk <>
-
- name_incl_path db ?
- BSegEnd@
-
-
- CSeg@
- assume ds:DGROUP
-
- ;----------------------------------------------------------------
- ; static int pascal check_dir(void) ;
- ; check a single directory for both .COM and .EXE
- ;----------------------------------------------------------------
- Proc@ CHECK_DIR,__PASCAL__
- push es
- push di
- push ds
- pop es
- assume es:DGROUP
- mov found_ext,0 ; haven't found anything yet
- mov di,offset DGROUP:executable_path
- mov cx,size executable_path
- mov al,0
- cld
- repne scasb
- dec di
- ; now that we have the end of the name, scan backward to check extension
- mov bx,di
- mov dl,0
- ext_scan_loop:
- dec di
- cmp di,offset DGROUP:executable_path
- je had_no_ext
- mov al,[di]
- cmp al,'.'
- jne not_dot
- or dl,dl ; have we seen a wildcard?
- jne got_dot
- or found_ext,USER_EXT ; yes, user specified a particular extension
- jmp short got_extension
- not_dot:
- cmp al,'/'
- je had_no_ext
- cmp al,'\'
- je had_no_ext
- cmp al,':'
- je had_no_ext
- cmp al,'*'
- je got_wildcard
- cmp al,'?'
- jne ext_scan_loop
- got_wildcard:
- mov dl,1
- jmp ext_scan_loop
- had_no_ext:
- mov di,bx ; back to end of name
- mov byte ptr [di],'.' ; append a period
- got_dot:
- inc di
- mov word ptr [di],'*' ; append an asterisk wildcard and NUL
- got_extension:
- mov ah,2Fh ; get DTA
- MSDOS@
- assume es:NOTHING
- push es ; and store address for later
- push bx
- mov dx,offset DGROUP:ffb
- mov ah,1Ah ; set DTA to findfirst block
- MSDOS@
- mov ah,4Eh
- mov cx,23h ; search for archive,hidden,and read-only
- check_dir_loop:
- mov dx,offset DGROUP:executable_path
- MSDOS@
- jc check_no_more
- test found_ext,USER_EXT
- jnz check_OK
- mov bx,offset DGROUP:ffb.?ffb_name
- check_found_ext_loop:
- mov al,[bx]
- inc bx
- cmp al,0
- je checked_ext
- cmp al,'.'
- jne check_found_ext_loop
- cmp word ptr [bx],'OC'
- jne not_com_ext
- cmp byte ptr [bx+2],'M'
- jne not_com_ext
- or found_ext,COM_EXT
- jmp short check_successful
- not_com_ext:
- cmp word ptr [bx],'XE'
- jne checked_ext
- cmp byte ptr [bx+2],'E'
- jne checked_ext
- or found_ext,EXE_EXT
- checked_ext:
- mov ah,4Fh
- jmp check_dir_loop
- check_no_more:
- test found_ext,COM_EXT or EXE_EXT
- je check_failed ; neither .COM nor .EXE found
- check_successful:
- mov word ptr [di],'OC'
- mov ax,'M'
- test found_ext,COM_EXT
- jne check_succeeded
- mov word ptr [di],'XE'
- mov ax,'E'
- check_succeeded:
- mov word ptr [di+2],ax
- check_OK:
- mov bx,dx
- jmp short check_dir_done
- check_failed:
- xor bx,bx
- check_dir_done:
- pop dx ; get back original DTA
- pop ax
- push ds
- mov ds,ax
- mov ah,1Ah
- MSDOS@ ; restore DTA
- pop ds
- pop di
- pop es
- or bx,bx ; set ZF if failed
- ret
- EndProc@ CHECK_DIR,__PASCAL__
-
- ;----------------------------------------------------------------
- ; 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
- if ldata
- @name = dword ptr [bp+2+cPtrSize]
- else
- @name = word ptr [bp+2+cPtrSize]
- endif
- ; start of subroutine
- push bp
- mov bp,sp
- push es
- push di
- push si
- ; set up pointer to environment
- mov es,_psp@
- mov es,es:[002Ch]
- xor di,di
- jmp short find_path
- find_path_loop:
- cmp byte ptr es:[di],0
- je found_path
- find_path_loop2:
- inc di
- cmp byte ptr es:[di-1],0
- jne find_path_loop2
- find_path:
- cmp word ptr es:[di],'AP'
- jne find_path_loop
- cmp word ptr es:[di+2],'HT'
- jne find_path_loop
- cmp byte ptr es:[di+4],'='
- jne find_path_loop
- add di,5
- found_path:
- mov word ptr env+2,es
- mov word ptr env,di
- mov di,offset DGROUP:executable_path
- cld
- search_loop:
- mov name_incl_path,0
- push ds
- pop es
- assume es:DGROUP
- ; append @name to executable_path
- pushDS_
- LDS_ si,@name
- copy_cur_loop:
- cmp di,offset DGROUP:executable_pad
- jae copy_cur_done
- lodsb
- stosb
- cmp al,'/'
- je name_has_path
- cmp al,'\'
- jne name_no_path
- name_has_path:
- mov name_incl_path,1
- name_no_path:
- or al,al
- jnz copy_cur_loop
- copy_cur_done:
- popDS_
- call check_dir@
- jnz search_successful
- cmp name_incl_path,0
- jne search_failed ; don't look at PATH unless simple filename
- les bx,env
- 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]
- cmp al,'/' ; was last char a slash or backslash?
- je dir_has_slash
- cmp al,'\'
- je dir_has_slash
- cmp al,':' ; no slash if only drive letter
- je dir_has_slash
- mov byte ptr [di],'/'
- inc di
- dir_has_slash:
- 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 _doserrno@,2 ; file not found
- xor ax,ax
- if ldata
- xor dx,dx
- endif
- search_done:
- pop si
- pop di
- pop es
- pop bp
- ret dPtrSize
- EndProc@ __SPAWN_SEARCH,__PASCAL__
-
- CSegEnd@
- END
-