home *** CD-ROM | disk | FTP | other *** search
-
- ; FILENAME: IEXECDOS.ASM
- ;
- ; Copyright (c) 1990, 1992 by Borland International, Inc.
- ;
- ; DESCRIPTION: This module implements the routines that handle calling
- ; DOS to perform a command on each file that is found by WHEREIS.
- ; This module uses ideal mode syntax.
- ;
- ; This module looks for the location of COMMAND.COM to enable the
- ; running of the commands. Since many matching files may be found,
- ; and COMMAND.COM is called to execute the given DOS command for each
- ; file that is found, it is best if COMMAND.COM is located in a ramdisk.
- ;
- ; ASSEMBLY INSTRUCTIONS: To assemble this module use the following
- ; TASM command line.
- ;
- ; TASM /m /dMDL=memorymodel iparam
- ;
- ; /m in the above command line allows TASM to resolve jumps and other
- ; operations to their shortest form and get rid of extra NOPs.
- ; 'memorymodel' in the above command line may be replaced by TINY, SMALL,
- ; MEDIUM, COMPACT, LARGE or HUGE. If assembling this module to run on
- ; a 286/386 machine, turn on the P286 directive in order to take advantage of
- ; 286/386 specific instructions. I.E.
- ;
- ; TASM /m /dMDL=memorymodel /jP286 iparam
- ;
-
- ;DO_SAMPLE_COMMAND equ 1 ; Enable this to execute a sample DIR command
- ; ; when the command line is being parsed.
-
- jumps
-
- %tabsize 4
-
- ifndef MDL
- display "Error: This module requires that you provide a memory model"
- display " definition on the command line. I.E. /dMDL=SMALL."
- err ; Force a fatal error
- else
-
- ideal ; Use TASM's Ideal mode
- % model MDL,pascal ; Define the memory model
-
- include "dos.inc"
- include "idos.inc"
- include "kbd.inc"
- include "iwhglobl.inc"
- include "imacros.mac"
-
- dataseg
- NO_COMMAND_GIVEN equ 0
- COMMAND_GIVEN equ 1
- DosCommandGiven db NO_COMMAND_GIVEN
-
- COMMAND_BUFFER_LENGTH equ 200
- ; Stores the command given on command line
- DosCommandBuffer db COMMAND_BUFFER_LENGTH dup (?)
-
- ; The DOS command in quotes will include some special escape sequences
- ; that will cause the name of the file to be inserted in various ways.
- ;
- ; %1 - The full path, filename and extension
- ; %2 - Filename and extension (no path)
- ; %3 - Only the path
- ; %4 - Only the filename before the extension followed by a .
- ; %5 - Only the extension, preceeded by a .
-
- ; This is placed at the start of COMMAND.COM command strings.
- StartOfBuff db '/C ',0
-
- ; Store the actual command that is executed. Any %x directives in
- ; the above command buffer are converted to their actual values
- ; as the above command is transfered into the following buffer.
- ; 32 extra bytes are an overrun buffer.
- CommandToDo db COMMAND_BUFFER_LENGTH+32 dup (?)
-
- ; Needed for the call to execute COMMAND.COM
- ParamBlock dw 7 dup (0)
-
- ComspecTag db 'COMSPEC=',0
-
- ; Pointer into the environment block for start of COMMAND.COM location
- ComspecSeg dw 0 ;Not changed from zero if no comspec found.
- ComspecOfs dw ?
-
- MakePascalString NoComspecMssg,<"COMSPEC= not found in environment!",13,10>
-
- codeseg
-
- ; The environment block is a group of null terminated strings.
- ; A string beginning with zero signals the end of the eviroment block.
-
- proc SearchEnvironment
- ; This routine searches for a variable in the environment block.
- ;
- ; Input
- ; DS:SI - Points to a string like "NAME=" which is to be
- ; found in the environment. It should be an ASCIIZ string.
- ; Output
- ; If the variable is found,
- ; AL - 0
- ; ES:DI - Points to string after the = sign in the environment.
- ; If the variable is not found,
- ; AL is nonzero.
- ; Registers modified
- ; all
-
- cld ;Set direction for scanning to increment
-
- ; Set ES:DI to environment block
- push ds
- mov ax,@data ; Reset to our datasegment since the "NAME="
- ; might be in another segment.
- mov ds,ax
- mov es,[PspAddress]
- mov es,[es:psp.EnvironmentBlock]
- xor di,di
- pop ds
- @@CheckEnvironmentEnd:
- mov bx,si ;initialize BX pointer to name to find
- mov al,[byte es:di]
- or al,al
- je @@MatchFailed ;jump if end is found
-
- @@CheckNextByte:
-
- mov al,[bx] ;get character to match.
-
- or al,al ;if end of name we are done!
- jz @@MatchCompleted ; (AL will be zero)
-
- cmp al,[byte es:di] ;compare to char in environment block
- jne @@FindNextString ;jump if match failed
- inc bx
- inc di
- jmp @@CheckNextByte
-
- @@FindNextString:
- xor al,al ;scan forward in Environment Block
- mov cx,0FFFFh ;for zero byte.
- repnz scasb
- jmp @@CheckEnvironmentEnd ;go compare next string
-
- @@MatchFailed:
- inc al ;return al<>0 as failure flag
-
- @@MatchCompleted: ;all matched, return ES:DI pointing
- ; to parameter. al = 0
- ret
- endp SearchEnvironment
-
-
- ifdef DO_SAMPLE_COMMAND
- ; Show a sample of the proper way to call COMMAND.COM
- dataseg
- SampleCommand db 9,'/C DIR C:',13
- codeseg
- proc SampleDosCommand
- ; This routine calls COMMAND.COM to do the DIR command.
- ;
- mov cx,seg SampleCommand
- mov dx,offset SampleCommand
- call DoDosCommand
- ret
- endp SampleDosCommand
- endif
-
- proc DoDosCommand
- ; This procedure executes the command string pointed at by DX:CX
- ; by giving it to COMMAND.COM.
- ; This routine is not reentrant because of local code segment
- ; data storage at end of routine.
- ;
- ; Input
- ; None
- ; Output
- ; None
- ; Calling conventions
- ; NA
- ; Registers modified
- ; all
-
- push ds
- mov ax,seg ParamBlock
- mov es,ax
- mov bx,offset ParamBlock
-
- mov [word es:bx+4],cx ; Load the location of the command tail
- mov [word es:bx+2],dx ; for the command.
-
- mov [Orig_SS],SS
- mov [Orig_SP],SP
-
- mov ax,[ComSpecSeg]
- or ax,ax
- jz @@Skip ; Skip over EXEC if our segment is still zero.
- ; That means that no Comspec was found.
-
- mov dx,[ComspecOfs]
- mov ds,ax
-
- mov ax,4b00h
- int 21h
- @@Skip:
- mov ss,[Orig_SS]
- mov sp,[Orig_SP]
- pop ds
- ret
-
- ; Preserves the location of our stack.
- Orig_SS dw ?
- Orig_SP dw ?
- endp DoDosCommand
-
- proc ParseDosCommand
- ; This procedure initializes all variables and data structures
- ; used for executing the DOS command.
- ;
- ; Input
- ; ES:DI - Points to DOS command which is surrounded by quotes.
- ; It is a pascal style string
- ; Output
- ; Carry set if a command has already been specified
- ; Calling conventions
- ; NA
- ; Registers modified
- ; all
-
- cmp [DosCommandGiven],COMMAND_GIVEN
- jne @@FirstUse
- stc ; An error because a command was already specified
- jmp @@Exit
-
- @@FirstUse:
- push es di ; Preserve pointer to DOS command
- ; We need to find COMMAND.COM before we can know that we can
- ; do a DOS command.
- mov si,offset ComspecTag ;DS:SI string to match
- call SearchEnvironment ;go search environment
- or al,al
- jne ComspecNotFound
-
- mov [ComspecSeg],es ; If it was found, ES:DI is stored.
- mov [ComspecOfs],di
- jz FreeExtraMemory
-
- ComspecNotFound:
- call WritePascalString,ds,offset NoComspecMssg
-
- FreeExtraMemory:
- ; We need to give up extra memory.
- mov bx,zzzzzseg ; Location of first segment of free memory
- mov ax,[PspAddress] ; PSP segment
- sub bx,ax ; BX now contains paragraphs used
- ; by this program.
- mov es,ax
- mov ah,4ah
- int 21h
-
- ifdef DO_SAMPLE_COMMAND
- call SampleDosCommand
- endif
- pop di es ; Restore pointer to DOS command
-
- ; Check if the final character is a quote and
- ; remove it if it is.
- xor bh,bh ; Get length of string in BX
- mov bl,[es:di]
-
- mov al,[es:di+bx] ; Load last character of string
- call IsDelimiter
- jnc RemoveLeadingQuote
-
- RemoveTrailingQuote:
- dec [byte ES:DI] ; Remove the trailing delimiter
-
- RemoveLeadingQuote:
- push es di ; Preserve the location of the DOS command
- mov cx, 1 ; Remove the first character
- mov ax, 1 ; from the string
- call DeleteChar,es,di
- pop di es ; Restore the location
-
- ; Copy the command to the DOS command buffer
- xor ah,ah
- mov al,[byte es:di]
- inc ax
-
- call ByteCopy,es,di,seg DosCommandBuffer,Offset DosCommandBuffer
-
- ; Set flag so we know that a command was given.
- mov [DosCommandGiven],COMMAND_GIVEN
- clc ; No error
- @@Exit:
- ret
- endp ParseDosCommand
-
-
- dataseg
- ; Local data area for ExecuteDosCommand
-
- ; The following act as pointers to the data for this invocation of
- ; ExecuteDosCommand.
- DirectoryPath dw ?
- FileNameSeg dw ?
- FileName dw ?
-
- codeseg
- proc ExecuteDosCommand
- ; This procedure actual executes the DOS command, if given, for
- ; each file that is found.
- ;
- ; Input
- ; ax:si - Offset of filename
- ; di - offset of currentdir
- ; Output
- ; none
- ; Calling conventions
- ; NA
- ; Registers modified
- ; all except es
-
- mov [DirectoryPath],di
- mov [FileNameSeg],ax
- mov [FileName],si
-
- push es
- cmp [DosCommandGiven],COMMAND_GIVEN
- jne @@Exit
-
- ; Blank out the buffer for the command to do.
- cld ; Autoincrement
- mov ax,seg CommandToDo
- mov es,ax
- mov di,offset CommandToDo
- mov cx,COMMAND_BUFFER_LENGTH
- mov al,0
- rep stosb
-
- ; We need to go into a loop of copying from the input command
- ; string until we find a %
-
- mov di,offset CommandToDo ; For results es:di
- xor cl,cl ; Length of output string
- inc di ; Move over the leading length byte
-
- mov si,offset StartOfBuff
- call CopyAsciizString ; Copy the starting /C
-
- mov si,offset DosCommandBuffer ; For original command ds:si
- mov ch,[si] ; Length of original string
- inc si ; Move over the leading length byte
-
-
- @@ProcessChar:
- or ch,ch
- jz SourceExhausted
- lodsb ; Load current byte
- dec ch ; One less character to get
-
- cmp al,'%'
- je @@ProcessSpecial
- @@EmitChar:
- stosb ; This route handles regular characters
- inc cl ; Increment length of output string
- cmp cl,COMMAND_BUFFER_LENGTH-1
- jae SourceExhausted ; Force early termination if we run out of room!
- jmp @@ProcessChar
-
- @@ProcessSpecial: ; We saw a % sign.
- or ch,ch
- jz @@EmitChar ;Output because there is nothing more after it
- lodsb
- dec ch
- ; Try to recognize one of the %x directives:
- cmp al,'1'
- je Process1
- cmp al,'2'
- je Process2
- cmp al,'3'
- je Process3
- cmp al,'4'
- je Process4
- cmp al,'5'
- je Process5
-
- ; We don't recognize it, so output the %x unchanged.
- mov [byte es:di],'%' ; Put out the % that got us here
- inc cl ; Increment length of output string
- inc di
- jmp @@EmitChar ; Output the character in AL
-
-
- Process1:
- call EmitPath
- cmp cl,COMMAND_BUFFER_LENGTH-1
- jae SourceExhausted ; Force early termination if we run out of room!
- Process2:
- call EmitFileRoot
- cmp cl,COMMAND_BUFFER_LENGTH-1
- jae SourceExhausted ; Force early termination if we run out of room!
- jmp Process5
-
- Process3:
- call EmitPath
- jmp @@ProcessChar
-
- Process4:
- call EmitFileRoot
- call EmitDot
- jmp @@ProcessChar
-
- Process5:
- Call EmitDot
- call EmitExtension
- jmp @@ProcessChar
-
- SourceExhausted:
- ;We need to fill in the length byte, along with a 13 at the end.
- mov al,13
- stosb
- mov [CommandToDo],cl ; Fill in the length byte
-
- mov cx,seg CommandToDo
- mov dx,offset CommandToDo
- call DoDosCommand
-
- @@Exit:
- pop es
- ret
- endp ExecuteDosCommand
-
-
-
- proc EmitPath
- ; This routine writes the drive and path to the output command.com string
-
- push si ds
-
- mov si,offset Drive
- call CopyPascalString
-
- mov si,[DirectoryPath]
- cmp [byte ds:si],'A'
- jl @@NoBackSlash
- dec si
- @@NoBackSlash:
- call CopyAsciizString
-
- mov ax,seg SwitchChar
- mov ds,ax
- mov si,offset SwitchChar
- call CopyPascalString
-
- pop ds si
- ret
- endp EmitPath
-
-
-
- proc EmitFileRoot
- ; This routine writes the part of the filename that is before the
- ; extension to the output string that will be sent to COMMAND.COM
-
- push si ds
- mov si,[FileName]
- mov ax,[FileNameSeg]
- mov ds,ax
-
- mov al,'.'
- call CopyTerminatedString
- pop ds si
- ret
- endp EmitFileRoot
-
-
-
- proc EmitExtension
- ; This routine writes the extension of the current file to the
- ; output string that will be sent to COMMAND.COM
-
- push si ds
- mov si,[FileName]
- mov ax,[FileNameSeg]
- mov ds,ax
-
- mov al,'.'
- @@CheckAgain:
- mov ah,[ds:si]
- cmp ah,al
- je @@DotFound
- or ah,ah
- jz @@Exit ; Quit searching if a zero is found
- inc si
- jmp @@CheckAgain
- @@DotFound:
- inc si
- call CopyAsciizString
- @@Exit:
- pop ds si
- ret
- endp EmitExtension
-
-
-
- proc EmitDot
- ; This routine outputs a . to the string to be sent to command.com.
-
- mov [byte es:di],'.' ; Put out the .
- inc cl
- inc di
- ret
- endp EmitDot
-
-
- ; The following string copy routines are special for this module.
- ; DS:SI point to the source string. (DS:SI are preserved.)
- ; ES:DI Point to the destination string area. (ES:DI is not preserved.)
- ; CL is updated for every byte output to ES:DI.
-
- proc CopyPascalString
- ; Copy pascal type string to ES:DI, but omit the length byte.
- xor bx,bx
- mov al,[ds:si]
- add cl,al
-
- @@CopyChar:
- mov ah,[ds:si+1+bx]
- mov [es:di],ah
- inc di
- inc bx
- dec al
- jnz @@CopyChar
-
- ret
- endp CopyPascalString
-
-
-
- proc CopyAsciizString
- ; Copy a string that is terminated by a zero.
- xor al,al
- call CopyTerminatedString
- ret
- endp CopyAsciizString
-
-
-
- proc CopyTerminatedString
- ; Copy a string terminated by any character.
- ; al contains character to stop copy. Normally 0 for ASCIIZ strings
- ; Note that the terminator is not copied.
- xor bx,bx
-
- @@CopyMoreChar:
- mov ah,[ds:si+bx]
- cmp ah,al
- jz @@AtEnd
- mov [es:di],ah
- inc di
- inc bx
- inc cl
- jnz @@CopyMoreChar
- @@AtEnd:
- ret
- endp CopyTerminatedString
-
-
-
-
-
-
- segment zzzzzseg ; Dummy final segment for calculating program size
- ; to release memory back to DOS.
- ends zzzzzseg
-
- endif ; ifndef MDL
-
- end
-
-
-