home *** CD-ROM | disk | FTP | other *** search
- ; WILD Public Domain 1988 by Charles Lazo III, v1.0
-
- ; WILD.ASM This program is used to run any other program (or DOS command)
- ; by expanding program wild card parameters given on the command
- ; line. E.g., WILD PROG *.* would run a program, say PROG.EXE,
- ; multiple times and supply it each time with a file from the
- ; current directory matching *.* (i.e., every file in the current
- ; directory would be supplied to PROG for execution).
-
- rt equ 0dh
- lf equ 0ah
- of equ offset
- bptr equ byte ptr
- wp equ word ptr
-
- code segment
- assume cs:code, ds:code
-
- org 2ch
- env_seg dw ? ; pointer to segment of our environment
-
- org 100h
- begin: jmp start
-
- ;-------------------------------------------------------------------------------
- ; The wild card specification is placed here at the bottom of our stack to avoid
- ; having to specially set aside space for it. It is used by the find_first
- ; routine to find the first file in the current directory meeting the wild card
- ; specification using the DOS Find First function.
- ;-------------------------------------------------------------------------------
- wild_spec db 16 dup('STACK ') ; 128 bytes for stack
- our_stack label word
-
- ss_save dw ? ; place to store ss:sp
- sp_save dw ?
-
- memory_used dw ? ; keep track of memory paragraphs used
- env_size dw ? ; number of bytes in the environment stored here
- cspc_addr label dword
- dw 2 dup(?); store address of comspec variable here
- left_blank dw ? ; stores pointer to start of wild card spec
- right_blank dw ? ; stores pointer to end of wild card spec
- copy_size dw ? ; stores size of command on command line (WILD)
- buffer_ptr dw 0 ; pointer to buffer for list of filenames
-
- switches db 0 ; record presence of QUERY & NOEXT here
- file_attr dw 0 ; store file attributes for file find
-
- cmd_line db 128 dup(0) ; save original command line here
-
- cmdl db ?,'/c',128 dup(?) ; command line for EXEC
-
- ;-------------------------------------------------------------------------------
- ; The parameter table to be passed to the DOS EXEC function:
- ;-------------------------------------------------------------------------------
- params dw ? ; segment of environment block stored here
- dw of cmdl ; offset of command line for program EXECed
- dw ? ; segment of command line for program EXECed
- dw 55h ; offset of first FCB
- dw ? ; segment of first FCB
- dw 65h ; offset of second FCB
- dw ? ; segment of second FCB
-
- ;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
- ; The following routines (up to the label buffer:) operate under the assumption
- ; that both ds and es are set to the code segment of WILD.
- ;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-
- ;-------------------------------------------------------------------------------
- ; When the WILD environment variable has NOEXT in its assignment string, then
- ; filename extensions are ignored (not supplied) when commands are passed to
- ; the DOS EXEC function. This routine will remove any extension from the file-
- ; name in the DTA placed there by the DOS Find First and Continue File Search
- ; functions if NOEXT was found in the WILD environment variable. The extension
- ; is removed by replacing the period separating the main part from the extension
- ; with a null. Note that if a period is the only part of the filename, then it
- ; must be the dot representing the current directory so it is not removed.
- ;-------------------------------------------------------------------------------
-
- remove_ext? proc near ; removes any extension from filename
- test switches,noe ; is WILD NOEXT env variable set?
- jz no_remove ; no, don't remove extension
- xor al,al ; find null terminating filename
- mov cx,14 ; max number of characters in ASCIIZ+1
- cld ; (for maintenance and documentation)
- repne scasb ; search for null
- sub di,9eh ; compute number of filename characters
- mov cx,di ; and place it in cx for next search
- mov al,'.' ; search for period prior to extension
- mov di,9eh ; offset of filename in DTA
- repne scasb ; search for period
- jcxz no_remove ; can't remove extension if not there
- cmp di,9fh ; if the period was the ONLY character,
- jz no_remove ; then it is the current directory
- mov bptr [di-1],0 ; set it to null to remove the extension
- no_remove: ret
- remove_ext? endp
-
- ;-------------------------------------------------------------------------------
- ; find_size computes the length of a filename in the DTA placed there by the DOS
- ; find first and continue file search functions. The length of the filename is
- ; returned in cx (the null character at the end of the ASCIIZ string is included
- ; in the count). This routine is similar to file_size, qv.
- ;-------------------------------------------------------------------------------
-
- find_size proc near ; find size of filename (returned in cx)
- call remove_ext? ; eliminate filename extension?
- xor al,al ; find null at end of ASCIIZ filename
- mov di,9eh ; offset of filename in DTA
- mov cx,14 ; max number of characters in ASCIIZ+1
- cld ; (for maintenance and documentation)
- repne scasb ; search for null in ASCIIZ filename
- sub di,9eh ; compute number of filename characters
- mov cx,di ; return value in cx
- ret
- find_size endp
-
- ;-------------------------------------------------------------------------------
- ; In this routine we check to see if there is enough memory presently allocated
- ; for the filename buffer to place another filename in the buffer. First di is
- ; is set to the location in the buffer where the next filename will go. If not
- ; enough memory has been allocated to allow the placement of another filename
- ; in the buffer, then more memory is allocated. By using only the memory that
- ; is needed by the buffer (additional memory is allocated in blocks of 16 para-
- ; graphs or 256 bytes; an arbitrary value) the remaining memory can be used in
- ; the EXEC call.
- ;-------------------------------------------------------------------------------
-
- set_di proc near ; sets di to point to next available
- mov di,buffer_ptr ; location in filename buffer
- push cx ; save filename size
- or di,di ; is it zero (uninitialized)?
- jz init_di ; yes, point it to start of buffer
- mov bx,di ; use bx to find paragraphs used now
- add bx,0fh ; round up to next paragraph
- shr bx,1 ; determine paragraph count
- shr bx,1
- shr bx,1
- shr bx,1
- inc bx ; reserve one more than used
- mov ax,memory_used ; memory paragraphs presently allocated
- cmp bx,ax ; is memory to be used > allocated?
- ja get_more ; yes, get more memory
- di_set: pop cx ; restore filename size
- ret
- get_more: add ax,16 ; ask for 256 more bytes (16 paragraphs)
- mov bx,ax ; request sent in bx
- mov dx,ax ; store in dx to assure request granted
- mov ah,4ah ; DOS memory modify function (es is ok)
- int 21h ; ask DOS for it
- cmp bx,dx ; DOS give what we wanted?
- mov dx,of mem_need ; address error message in case not
- jz got_it ; got requested memory
- jmp error_exit ; nope, DOS don't have it, terminate
- init_di: mov di,of buffer
- jmp short di_set ; exit with di at start of buffer
- got_it: mov memory_used,bx ; update memory allocated
- pop cx ; restore filename size
- ret
- set_di endp
-
- ;-------------------------------------------------------------------------------
- ; With this call we copy the filename in the DTA (placed there by DOS Find First
- ; and Continue File Search functions) into the filename buffer.
- ;-------------------------------------------------------------------------------
-
- store_filename proc near ; store filename of file find in buffer
- call find_size ; find size of filename in DTA (to cx)
- call set_di ; set di to next location in buffer
- mov si,9eh ; offset of filename in DTA
- cld ; (for maintenance and documentation)
- rep movsb ; move ASCIIZ filename to buffer
- mov buffer_ptr,di ; update buffer pointer
- ret
- store_filename endp
-
- ;-------------------------------------------------------------------------------
- ; This one is similar to the find_size routine in that the size of a file is
- ; returned in cx. While the find_size routine gets its input from the filename
- ; in the DTA, this one finds sizes of filenames set into the filename buffer.
- ; Additionally it differs in that find_size includes the terminal null in the
- ; count and this one does not. Also the zero flag is set if no more filenames
- ; exist (else reset).
- ;-------------------------------------------------------------------------------
-
- file_size proc near ; size of next filename in buffer to cx
- mov di,buffer_ptr ; get current buffer position
- cmp bptr [di],0 ; was the last the final filename?
- jz last_done ; yes, return with zero flag set
- mov cx,di ; save current buffer position
- push cx
- mov cx,14 ; longer than any ASCIIZ filename string
- mov al,0 ; search for null in ASCIIZ filename
- cld ; (for maintenance and documentation)
- repne scasb ; find the null
- mov buffer_ptr,di ; store new buffer position
- pop cx ; recover last buffer position
- sub di,cx ; compute size of filename in cx
- xchg cx,di
- dec cx ; discard null and reset the zero flag
- last_done: ret
- file_size endp
-
- ;-------------------------------------------------------------------------------
- ; A copy of the command line as given by the user (WILD's command line) is
- ; maintained at the location cmd_line. The variables left_blank and right_blank
- ; point to the first and last characters of the wild card specification within
- ; cmd_line when this routine is called the first time or the first and last
- ; characters of the previous filename when the routine is called at succeeding
- ; times. This blank is resized--either made larger or smaller--depending upon
- ; the size of the current filename that is to be copied into it.
- ;-------------------------------------------------------------------------------
-
- resize_blank proc near ; adjust filename blank to right size
- mov ax,left_blank ; first character of blank
- mov bx,right_blank ; last character of blank
- sub bx,ax ; compute length of blank
- inc bx
-
- mov di,right_blank ; point to last character of blank
- mov al,rt ; search for return character
- push cx ; save filename size
- mov cx,127 ; larger than necessary, so ok
- cld ; (for maintenance and documentation)
- repne scasb ; find the return character
- dec di ; point di to return character
- mov cx,di ; compute number to move in cx
- mov ax,right_blank
- sub cx,ax
- pop ax ; get filename size
-
- cmp ax,bx ; greater, less than, or equal?
- je rb_done ; finished if equal
- jb decrease ; less than, so decrease blank
- sub ax,bx ; compute amount filename is greater
- mov si,di ; point si to return character
- add di,ax ; di to new location of return character
- std ; decrement move this time
- rep movsb ; make room for filename
- mov bx,right_blank ; adjust this variable
- add bx,ax
- mov right_blank,bx
- mov bx,copy_size ; and this one also
- add bx,ax
- mov copy_size,bx
- mov bl,cmd_line ; and this one too
- add bl,al
- mov cmd_line,bl
- rb_done: ret
-
- decrease: sub bx,ax ; compute amount blank is greater
- mov si,right_blank ; point to first character after blank
- inc si
- mov di,si ; compute new location for these chars
- sub di,bx
- cld ; (for maintenance and documentation)
- rep movsb ; resize blank to filename size
- mov ax,right_blank ; adjust this variable
- sub ax,bx
- mov right_blank,ax
- mov ax,copy_size ; and this one also
- sub ax,bx
- mov copy_size,ax
- mov al,cmd_line ; and this one too
- sub al,bl
- mov cmd_line,al
- ret
- resize_blank endp
-
- ;-------------------------------------------------------------------------------
- ; cx contains filename size due to maintenance of this value on the stack while
- ; the resize_blank routine was called previous to the call to this one. The
- ; routine copies a filename from the filename buffer into a holding area (the
- ; location in cmd_line called blank) prior to it's being copied to the command
- ; line used by EXEC.
- ;-------------------------------------------------------------------------------
-
- copy_filename proc near ; copy a buffer filename to cmd_line
- mov si,buffer_ptr ; point si to current filename
- sub si,cx ; (since file_size updated buffer_ptr
- dec si ; we must go back for current file)
- mov di,left_blank ; the place in cmd_line to copy to
- cld ; (for maintenance and documentation)
- rep movsb ; filename --> cmd_line
- ret
- copy_filename endp
-
- ;-------------------------------------------------------------------------------
- ; This routine prepares the next command line that will be passed to EXEC by
- ; using the next available filename from the filename buffer. If all filenames
- ; have been processed, then the zero flag is set on return, else it is reset.
- ;-------------------------------------------------------------------------------
-
- copy_command proc near ; copy command to EXEC's command line
- call file_size ; find size of filename (returned in cx)
- jz all_done ; no more, so return with zero flag set
- push cx ; save filename size
- call resize_blank ; adjust filename blank to right size
- pop cx ; restore filesize for copy_filename
- call copy_filename ; filename from buffer --> command line
-
- mov cx,copy_size ; get size of command line copy
- mov al,cmd_line ; set size of EXEC's command line
- add al,2 ; account for increase due to "/c"
- mov cmdl,al ; set in size for EXEC
- mov si,of cmd_line+1; copy command to be executed
- mov di,of cmdl+3 ; to proper location for EXEC
- cld ; (for maintenance and documentation)
- rep movsb ; do the copy
- or al,al ; al is nonzero so zero flag is reset
- all_done: ret
- copy_command endp
-
- ;-------------------------------------------------------------------------------
- ; If the WILD environment variable contains the QUERY option, then this routine
- ; prompts the user with "(Y/N/A)?" for Yes, No, or Abort. The zero flag is set
- ; on return if the user replies No, it is reset if the reply is Yes, and the
- ; carry flag is set if Abort is the reply (carry flag reset if Y or N). These
- ; flag settings are preserved by the calling routine, wild_prompt, so that the
- ; code that calls wild_prompt can test them. This code responds as if a Yes
- ; response were given if QUERY is not active.
- ;-------------------------------------------------------------------------------
-
- wild_query? proc near ; inquire Yes, No, or Abort if QUERY set
- test switches,que ; is QUERY set in switches variable?
- jz wq_yes ; no, return to caller as if Yes
- mov dx,of wq_prompt ; prompt to send to standard error
- mov cx,wqp_size ; number of characters to send
- mov bx,2 ; write to file handle 2 (std error)
- mov ah,40h ; with DOS function 40h
- int 21h
- wq_next: mov ah,7 ; DOS keyboard input without echo
- int 21h
- or al,al ; an ASCII character?
- jnz wq_ascii ; yes, process the response
- mov ah,7 ; no, get and discard auxiliary byte
- int 21h
- jmp short wq_next ; continue input
- wq_ascii: and al,0dfh ; capitalize
- mov response,al ; and store it for (possible) output
- cmp al,'Y' ; a Yes response?
- je wq_yes ; uhuh, reset zero flag and exit
- cmp al,'N' ; a No response?
- je wq_no ; yeah, just exit (ZF is set)
- cmp al,'A' ; an Abort response?
- je wq_abort ; yep, set carry flag and exit
- jmp short wq_next ; none of the above; try again
- wq_yes: or al,al ; reset zero flag to indicate Yes
- wq_no: pushf ; save flags
- mov dx,of response ; write this
- mov cx,1 ; one character
- mov bx,2 ; to standard error
- mov ah,40h ; with DOS function 40h
- int 21h
- popf ; recover return flags
- ret
- wq_abort: or al,al ; reset zero flag so not taken as No
- stc ; set carry flag to indicate abort
- jmp short wq_no ; write response to screen
- wq_prompt db ' (Y/N/A)? ' ; prompt user with <(Yes, No, Abort)?>
- wqp_size equ $-wq_prompt ; size of prompt
- response db ? ; place to store user response to query
- wild_query? endp
-
- ;-------------------------------------------------------------------------------
- ; Here we show the user the command that will be executed next by WILD and if
- ; the WILD environment variable contains the QUERY option, then we will prompt
- ; (Y/N/A)? also.
- ;-------------------------------------------------------------------------------
-
- wild_prompt proc near ; output to std out the command EXECed
- mov dx,of wild_pmt ; display "WILD>" lead in
- mov cx,wildpmt_size ; size of lead in
- mov bx,2 ; write to file handle 2 (std error)
- mov ah,40h ; with DOS function 40h
- int 21h
- mov dx,of cmdl+3 ; point to command to be EXECed
- mov cx,copy_size ; number of bytes to send to std out
- dec cx ; but not the return at end of line
- mov bx,2 ; write to file handle 2 (std error)
- mov ah,40h ; with DOS function 40h
- int 21h
- call wild_query? ; send a query?
- pushf ; save response
- mov dx,of wild_rtlf ; return/linefeed to std out
- mov cx,2 ; just 2 characters to send
- mov bx,2 ; write to file handle 2 (std error)
- mov ah,40h ; with DOS function 40h
- int 21h
- popf ; restore response
- ret
- wild_pmt db rt,lf,'WILD>' ; lead in for WILD
- wildpmt_size equ $-wild_pmt
- wild_rtlf db rt,lf ; newline after "prompt"
- wild_prompt endp
-
- find_rest: call store_filename ; store filename as ASCIIZ in buffer
- mov ah,4fh ; DOS continue file search function
- int 21h
- or ax,ax ; return code nonzero?
- jnz all_found ; yes, all files have been found
- jmp short find_rest ; continue file find
-
- all_found: mov di,buffer_ptr ; get file buffer pointer
- mov bptr [di],0 ; double null indicates end of buffer
- mov di,of buffer ; start now at beginning of buffer
- mov buffer_ptr,di ; to process filenames
- next_file: call copy_command ; copy command with filename to EXEC's
- ; copy of the command line
- jz exit ; zero flag set indicates completion
- call wild_prompt ; command to screen and maybe prompt
- jz next_file ; user said no to this one
- jc exit ; user wants to abort
- mov ss_save,ss ; save stack to restore upon return from
- mov sp_save,sp ; the EXEC
-
- lds dx,cspc_addr ; ds:dx points to name of prog to EXEC
- mov bx,of params ; es:bx points to parameter block
- mov ax,4b00h ; execute program after loading it
- int 21h
-
- mov ss,cs:ss_save ; restore our stack
- mov sp,cs:sp_save
-
- mov ax,cs ; cs --> ds, es
- mov ds,ax
- mov es,ax
- jmp short next_file
-
- exit: mov ax,4c00h ; terminate with error code 0
- int 21h
-
- buffer: ; store list of ASCIIZ filenames here prior to processing
-
- ;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
- ; The following routines will be used before the buffer is used and not again
- ; after the buffer begins to fill with ASCIIZ filenames from the current
- ; directory. Since memory is saved by overwriting them, that is why they are
- ; placed here. Even though this code and data will be overwritten as the file-
- ; name buffer begins to fill with files, the memory saved for the program's use
- ; includes all memory where this code and data reside. A filename buffer is
- ; used to store the names of files obtained from the current directory because
- ; after the EXEC function is used DOS somehow looses some of the information it
- ; needs for the performance of the Continue File Search function.
- ;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-
- ;-------------------------------------------------------------------------------
- ; We use this routine to check for the presence of a space, tab or the beginning
- ; of the command line in order to determine the location of the start of a wild
- ; card specification.
- ;-------------------------------------------------------------------------------
-
- space_tab_left proc near ; return with Z flag set if di points to
- cmp bptr [di],' ' ; a space
- je stl_z
- cmp bptr [di],9 ; a tab
- je stl_z
- cmp di,of cmd_line ; or the start of the command line
- je stl_z
- or al,al ; reset Z flag
- stl_z: ret
- space_tab_left endp
-
- ;-------------------------------------------------------------------------------
- ; Checks for invalid filename characters following a wild card character to
- ; signal the end of the wild card spec. Thus the space character--although it
- ; is not included in my PC DOS 3.20 manual as an invalid character (oversight?)
- ; --is included among them. Also the period, even though it is an invalid
- ; filename character is not included among those checked since it is valid as a
- ; character in a wild card specification (same with * and ?).
- ;-------------------------------------------------------------------------------
-
- check_invalid proc near ; return with Z flag set if di points to
- mov ah,[di] ; an invalid filename character
- push ax ; save wild card test character
- cmp ah,' ' ; space or less than?
- jbe ci_z ; yes, return with zero flag set
- mov si,of inv_chars ; point to set of invalid characters
- cld ; (for maintenance and documentation)
- get_inv: lodsb ; get one of these
- or al,al ; end of invalid character set?
- jz ci_nz ; yes, return with zero flag reset
- cmp ah,al ; an invalid character
- je ci_z ; yes, return with zero flag set
- jmp short get_inv ; test another
- ci_z: pop ax ; restore wild card test character
- xor ah,ah ; set zero flag
- ret ; return (zero flag is set)
- ci_nz: pop ax ; restore wild card test character
- or al,al ; reset zero flag
- ret
- inv_chars db '"/\[]:|< >+=;,',0 ; invalid filename characters
- check_invalid endp
-
- ;-------------------------------------------------------------------------------
- ; This routine will find the wild card specification in the copy of the command
- ; line (cmd_line), execute the DOS find first function, place the filename
- ; obtained from this function into the command line copy (cmd_line), copy this
- ; command into the command line that will be passed to EXEC, and then return.
- ; The location of the wild card spec in cmd_line is referred to by the term
- ; "blank", since this is a "fill in the blank" operation.
- ;-------------------------------------------------------------------------------
-
- find_first proc near ; find first file of wild card spec
- mov al,rt ; search the end of command line first
- mov di,81h ; start at first character
- mov cx,127 ; maximum is fewer, but this will do
- cld ; (for maintenance and documentation)
- repne scasb ; find return character
- sub di,81h ; compute number of characters to search
- mov copy_size,di ; store here for later use
-
- mov al,'*' ; first test for presence of an asterisk
- search_wild: mov cx,copy_size ; install number of characters to search
- mov di,of cmd_line+1; command line passed by DOS (copy)
- cld ; (for maintenance and documentation)
- repne scasb ; do search
- jcxz not_this_wild ; this wild card not found
-
- push di ; save position of char after wild card
- dec di ; move to wild card
- back_one: dec di ; test character left
- call space_tab_left ; check for space, tab or beginning
- jnz back_one ; go back a character and look again
- inc di ; point to first character in blank
- mov left_blank,di ; store position as start of blank
- pop di ; points to character after wild card
- dec di ; undone by next instruction
- over_one: inc di ; test one character right
- call check_invalid ; check if an invalid filename character
- jnz over_one ; go forward a character and look again
- dec di ; point to last character in blank
- mov right_blank,di ; store position as end of blank
- mov si,left_blank ; address blank for copy
- mov cx,di ; construct size of blank in cx
- inc cx
- sub cx,si
- mov di,of wild_spec ; copy blank (wild spec) here
- cld ; (for maintenance and documentation)
- rep movsb ; do the copy to work space
- mov bptr [di],0 ; make it an ASCIIZ string
- mov dx,of wild_spec ; address with ds:dx for find first
- mov cx,file_attr ; find files with these attributes
- mov ah,4eh ; DOS find first function
- int 21h
- or ax,ax ; return code nonzero?
- jnz none_found ; yes, no files were found, return
- xor ax,ax ; return code is zero
- none_found: ret
-
- not_this_wild: cmp al,'?' ; did we search for a "?" yet?
- je no_wild ; yes, no other wild
- mov al,'?' ; no, so search for it too
- jmp short search_wild
- no_wild: mov ax,255 ; return 255 if no wild card found
- ret
- find_first endp
-
- cspc_str db 'COMSPEC=' ; COMSPEC string to find in environment
- cspc_size equ $-cspc_str ; size of "COMSPEC=" string
-
- notice db rt,lf,'WILD v1.0 Public Domain 1988 by Charles Lazo '
- db 'III, CIS userid 72210,17',rt,lf
- notice_size equ $-notice
-
- bad_DOS db rt,lf,'WILD: Requires DOS version 2 or above.',rt,lf,0
- mem_need db rt,lf,'WILD: Not enough memory.',rt,lf,0
- no_comspec db rt,lf,"WILD: Can't find COMSPEC in environment."
- db rt,lf,0
- none_wild db rt,lf,'WILD: No wild card characters were found.'
- db rt,lf,0
- no_file db rt,lf,'WILD: No files were found.',rt,lf,0
-
- ;-------------------------------------------------------------------------------
- ; Execution is transferred here when an error has occured. The code that has
- ; transferred control here will place in dx the offset of the error message that
- ; will be sent to standard error. This error message must be terminated by a
- ; null. The program then exits with error level set to 1.
- ;-------------------------------------------------------------------------------
-
- error_exit: mov ax,cs ; assure ds and es at cs
- mov ds,ax
- mov es,ax
- mov di,dx ; find the null terminating error string
- xor al,al ; search for null
- cld ; (for maintenance and documentation)
- mov cx,0ffffh ; largest possible
- repne scasb ; find the null
- mov cx,di ; compute number of characters to send
- sub cx,dx ; in cx
- dec cx
- mov bx,2 ; send them to standard error
- mov ah,40h ; with DOS function 40h
- int 21h
- mov ax,4c01h ; exit with error code 1
- int 21h
-
- ;-------------------------------------------------------------------------------
- ; Execution comes here when the program begins. First the DOS version is
- ; checked to be sure it is 2 or greater, then all memory is released except that
- ; which is needed to continue operation after the filename buffer begins to fill
- ; with filenames from the current directory. (All code and data is retained,
- ; but that which lies beyond the label buffer: is overwritten by filenames as
- ; the filename buffer begins to fill. If more memory is needed, then it is
- ; allocated by the set_di routine.) The size of the environment is determined
- ; so that it can be used as a limit to the number of bytes to be searched for
- ; the two environment variables WILD and COMSPEC. Next the string "WILD=" is
- ; searched for in the environment and if found, then the two data variables,
- ; switches and file_attr (defined at the top of this file), are initialized
- ; based upon the settings in this string. Finally, the string "COMSPEC=" is
- ; searched for in the environment and if not found, the program sends a message
- ; to the screen and terminates with the error level set to 1. If COMSPEC is
- ; found its segment and offset are stored in the variable cspc_addr to be used
- ; later to find the program (usually COMMAND.COM) that shall be used as a shell
- ; to run the command given by the user.
- ;-------------------------------------------------------------------------------
-
- start: mov dx,of bad_DOS ; prepare wrong version message
- mov ah,30h ; get DOS version number
- int 21h
- cmp al,2 ; DOS ver 2 or greater?
- jae DOS_ok ; yes, good DOS version
- jmp short error_exit; else send error and exit
- DOS_ok: mov dx,of notice ; show notice information
- mov cx,notice_size ; length of notice message
- mov bx,2 ; send notice message to standard error
- mov ah,40h ; with DOS function 40h
- int 21h
- mov bx,of last ; assure all code retained
- mov ax,of buffer ; assure at least 256 bytes for buffer
- add ax,256
- cmp bx,ax ; use the larger of these two
- jae bx_good ; bx larger is good enough
- mov bx,ax ; make bx good enough
- bx_good: add bx,0fh ; round up to next paragraph
- shr bx,1 ; calculate paragraphs
- shr bx,1
- shr bx,1
- shr bx,1
- mov memory_used,bx ; save here for later use
- mov ah,4ah ; DOS modify block to reserve bx
- int 21h ; paragraphs for code and buffer
- mov dx,memory_used ; get number requested
- cmp bx,dx ; is number available same as requested?
- mov dx,of mem_need ; address memory needed error
- jz modify_ok ; okay, on modify memory block
- jmp error_exit ; error, not able to modify block
-
- modify_ok: mov sp,of our_stack ; move stack to memory owned by us
- mov si,80h ; offset of command line given us by DOS
- mov di,of cmd_line ; place to copy command line (it is
- cld ; overwritten by DOS find file calls)
- mov cx,128 ; copy 128 bytes (DOS legal limit)
- rep movsb
-
- mov ax,env_seg ; get segment of environment
- mov params,ax ; and place it in parameter table
- mov params+4,cs ; segment of command line
- mov params+8,cs ; segment of first FCB
- mov params+12,cs ; segment of second FCB
-
- jmp find_env_size ; determine size of environment
-
- ;-------------------------------------------------------------------------------
- ; This one searches the environment for the string pointed to by es:di. The
- ; number of characters in the string is provided in dx, bx has the number of
- ; bytes to be searched and ds:si points to the starting point of the search.
- ; If the string is found, then the carry flag is reset to indicate success and
- ; the offset of the string into the segment of the environment is returned in
- ; si. If the search fails, then the carry flag is set prior to return.
- ;-------------------------------------------------------------------------------
-
- search_str proc near ; search environment for string at di
- mov cx,bx ; set number of bytes to search
- next_byte: push cx ; save number of bytes to search
- push si ; save start positions
- push di
- mov cx,dx ; number of characters in string at di
- cld ; (for maintenance and documentation)
- repe cmpsb ; compare the two strings
- jcxz str_found ; found string at di in the environment
- pop di ; get 'em back
- pop si
- inc si ; bump pointer
- pop cx ; get count
- loop next_byte
- stc ; set carry; string at di not found
- ret
- str_found: pop di ; remove stacked registers
- pop si
- pop cx
- clc ; clear carry; string at di found
- ret
- search_str endp
-
- ;-------------------------------------------------------------------------------
- ; Here we search for the meaningful values that may be contained in the WILD
- ; environment variable. These values are QUERY, NOEXT, H, S, and D (capital-
- ; ization is not significant). The file WILD.DOC gives a description of the
- ; meaning of each. First the whole string is capitalized and then a search is
- ; made for QUERY and for NOEXT. The first and/or second bit of the byte
- ; switches is set depending upon the success of these searches. Then H(idden),
- ; S(ystem) and D(irectory) values are searched and if found, then corresponding
- ; bits are set in the file_attr variable. Also data for this and related code
- ; is defined at the end of this routine.
- ;-------------------------------------------------------------------------------
-
- wild_settings proc near ; set switches variable by WILD= string
- mov cs:ws_start,si ; save offset of WILD variable setting
- xor bx,bx ; count here the number of characters
- cld ; (for documentation and maintenance)
- ws_next: lodsb
- or al,al ; is it the null at end of ASCIIZ?
- jz ws_search ; yes, capitalization is done
- inc bx ; count it
- cmp al,'a' ; is it below an 'a'?
- jb ws_next ; yes, continue
- cmp al,'z' ; is it above a 'z'?
- ja ws_next ; yes, continue
- and bptr [si-1],0dfh; capitalize it
- jmp short ws_next ; continue
- ws_search: mov si,cs:ws_start ; get start of WILD variables
- mov di,of query ; search for QUERY
- mov dx,query_size ; size of query string
- call search_str ; do the search
- jc do_noext ; QUERY not found; look for NOEXT
- or cs:switches,que ; set bit 0 to indicate QUERY found
- do_noext: mov si,cs:ws_start ; get start of WILD variables
- mov di,of noext ; search for NOEXT
- mov dx,noext_size ; size of query string
- call search_str ; do the search
- jc do_hidden ; no NOEXT; look for hidden switch
- or cs:switches,noe ; set bit 1 to indicate NOEXT found
- do_hidden: mov si,cs:ws_start ; get start of WILD variables
- mov di,of hidden ; search for hidden string
- mov dx,hidden_size ; size of hidden string
- call search_str ; do the search
- jc do_system ; no hidden; look for system switch
- or cs:file_attr,hid; set bit 1 in file attribute
- do_system: mov si,cs:ws_start ; get start of WILD variables
- mov di,of system ; search for system string
- mov dx,system_size ; size of system string
- call search_str ; do the search
- jc do_direct ; no system; look for direct switch
- or cs:file_attr,sys; set bit 2 in file attribute
- do_direct: mov si,cs:ws_start ; get start of WILD variables
- mov di,of direct ; search for direct string
- mov dx,direct_size ; size of direct string
- call search_str ; do the search
- jc ws_done ; no direct; all done
- or cs:file_attr,dir; set bit 4 in file attribute
- ws_done: ret
- ws_start dw ? ; pointer to start of WILD env variables
- query db 'QUERY' ; string to find in WILD env variable
- query_size equ $-query
- noext db 'NOEXT' ; another string to find
- noext_size equ $-noext
- hidden db 'H' ; find this, then include hidden files
- hidden_size equ $-hidden
- system db 'S' ; find this, then include system files
- system_size equ $-system
- direct db 'D' ; find this, then directory files
- direct_size equ $-direct
- que equ 1 ; set into switches if QUERY present
- noe equ 2 ; set into switches if NOEXT present
- hid equ 2 ; set into file_attr if hidden string
- sys equ 4 ; set into file_attr if system string
- dir equ 16 ; set into file_attr if direct string
- wild_settings endp
-
- ;-------------------------------------------------------------------------------
- ; Find the size of the environment so only this number of bytes will be searched
- ; for environment strings.
- ;-------------------------------------------------------------------------------
-
- find_env_size: mov ax,env_seg ; segment of environment --> es
- mov es,ax
- xor di,di ; search begins at start of environment
- xor al,al ; search for nulls in environment
- mov cx,8000h ; environment is no larger than 32k
- next_word: repne scasb ; find a null
- scasb ; a double null here?
- jz found_env_end ; yes, signals end of environment block
- jmp short next_word ; else continue searching
-
- found_env_end: mov ax,8000h ; number of bytes in environment --> cx
- xchg ax,cx
- sub cx,ax
- mov env_size,cx ; store size of our environment
-
- ;-------------------------------------------------------------------------------
- ; Setup segment registers for environment searches.
- ;-------------------------------------------------------------------------------
- mov ax,env_seg ; segment of environment --> ds
- mov ds,ax
- push cs ; cs --> es
- pop es
- jmp short wild_env ; handle wild environment variables
-
- ;-------------------------------------------------------------------------------
- ; First search for the string "WILD=" in the environment and if it is found,
- ; then set program switches depending upon what the WILD environment variable
- ; is set to.
- ;-------------------------------------------------------------------------------
- wild_str db 'WILD=' ; WILD's environment variable string
- wild_size equ $-wild_str ; size of "WILD=" string
-
- wild_env: xor si,si ; point to start of environment
- mov dx,wild_size ; characters in string "WILD=" --> dx
- mov di,of wild_str ; address WILD environment string
- mov bx,cs:env_size ; number of bytes to search for string
- call search_str ; find WILD string (if present)
- jc do_cspc ; WILD string not found; do COMSPEC
- add si,wild_size ; point si to value of WILD variable
- call wild_settings ; record switch settings in environment
-
- ;-------------------------------------------------------------------------------
- ; Now, search for "COMSPEC=" in the environment. If it is found, then it will
- ; be used to provide the copy of COMMAND.COM to be used for the EXEC call(s).
- ; If it is not found, then we exit with an error message.
- ;-------------------------------------------------------------------------------
- do_cspc: mov bx,cs:env_size ; number of bytes to search for COMSPEC
- xor si,si ; point to start of environment
- mov dx,cspc_size ; characters in string "COMSPEC=" --> dx
- mov di,of cspc_str ; address COMSPEC string
- call search_str ; find COMSPEC string (if present)
- jnc comspec_found ; no carry, COMSPEC string was found
-
- mov dx,of no_comspec; tell can't find COMSPEC, then exit
- jmp error_exit
-
- comspec_found: add si,cspc_size ; make si point to COMSPEC value
- mov wp cs:cspc_addr,si ; store comspec offset
- mov wp cs:cspc_addr+2,ds ; store comspec segment
- push cs ; cs --> ds
- pop ds ; (now cs, ds, and es are all same)
- call find_first ; find the first file in the directory
- cmp ax,255 ; special return for no wild card found?
- jne wild_found ; no, check if a file was found
- mov dx,of none_wild ; send this message and end
- jmp error_exit
- wild_found: or ax,ax ; a file found?
- jnz none_here ; no, say so and end
- jmp find_rest ; yes, find the remainder of files
- none_here: mov dx,of no_file ; address no file message
- jmp error_exit
-
- last: ; offset of end of program. Used to assure that all code is
- ; retained with memory modify operation at the start of code.
-
- code ends
- end begin