home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
sampler0
/
xall.asm
< prev
next >
Wrap
Assembly Source File
|
1990-01-05
|
21KB
|
367 lines
PAGE 60,132
TITLE Xall - High speed eXeute in ALL subdirs utility
SUBTTL General Program description
;-----------------------------------------------------------------------------;
; Xall - eXecute any command in current directory plus all subdirectories ;
;-----------------------------------------------------------------------------;
; XALL 1.0 ■ PCDATA TOOLKIT Copyright (c) 1990 Ziff Communications Co. ;
; PC Magazine ■ Wolfgang Stiller ;
; ;
;-----------------------------------------------------------------------------;
;Purpose: ;
; XALL will eXecute any command in the current directory plus all ;
; subdirectories below that one. This program is written for high ;
; speed execution (lean and mean!). ;
;-----------------------------------------------------------------------------;
;Syntax: ;
; ;
;XALL anyDOScommand ;
; ;
; "anyDOScommand" may be any batch file, program, or DOS command. Any ;
; programs or batch files should be located in a ;
; directory specified in the DOS path (PATH=). ;
;-----------------------------------------------------------------------------;
;Remarks: ;
; "anyDOScommand" will be executed first in the current directory and ;
; then in each subdirectory subordinate to the current directory. This ;
; program has been optimized for speed and efficiency of execution. If ;
; execution is terminated, you will be in the directory currently being ;
; processed. This program does NOT check for execution of other ;
; programs that change the drive or directory. (Speed is the goal!) ;
; XALL has advanced error recovery and provides clear explanations to ;
; PCDATA Toolkit user of what has gone wrong, such as an ;
; invalid COMSPEC environment variable. ;
; ;
; XALL will return the following DOS errorlevels: ;
; ;
; 00 - normal completion ;
; 32 - any abnormal occurance - indicates fatal termination. ;
;-----------------------------------------------------------------------------;
;-----------------------------------------------------------------;
; Constants: ;
;-----------------------------------------------------------------;
BOX EQU 254 ;Small box character code
CR EQU 0Dh ; Carriage return
LF EQU 0Ah ; Line feed
CRLF EQU 0A0D ; CR+LF in one word
First_time EQU 00h ; Constant to indicate first time
Not_First_Time EQU 0FFh ; indicate NOT first time
Subdirectory_attrib EQU 10h ; Bit pattern to find directories
CSEG SEGMENT
ASSUME CS:CSEG, DS:CSEG,ES:CSEG,SS:CSEG
ORG 2Ch ;Segment of environment found here
Environment LABEL BYTE
ORG 7DH ;Just before paramter area in PSP
XALL_PARM LABEL BYTE
ORG 80h ;Normal DOS PSP parameter area
PSP_PARM LABEL BYTE
;*****************************************************************************
;** Main program begins here: XALL - Subdirectory Command eXecuter **
;** ---- **
;*****************************************************************************
ORG 100h ;This is a .COM type program
XALL:
MOV SP,OFFSET STACK_TOP ;Create new stack
MOV DX,OFFSET XALL_CR_MSG ;Copyright message
MOV AH,09h ;DOS print string function
INT 21h
MOV BX,offset Program_top ;End of program + 15 (segment roundng)
MOV CX,4 ;Prepare to div by 4 (calc # of paras)
SHR BX,CL ;Convert to segment address
MOV AH,4Ah ;Release uneeded memory
INT 21h
CALL Get_COMSPEC ;Locate the compsec in the environment
CALL Create_EXEC_parm_BLOCK ;Create parameter block for DOS EXEC
CALL Create_Command_tail ;Create /C command for COMMAND.COM
;***********************;
; MAIN loop begins here ;
;***********************;
EXEC_Next_Command: ;Come here to execute a command
;in each directory
CALL DISPLAY_XALL_MSG ;Display msg that we are this directry
;---------------------------------------------------------------------------;
; Use DOS EXEC function to invoke COMMAND.COM with user's specified command ;
; tail from the parameter area at 80h. ;
LDS DX,[Command_Adr] ;DS:DX is address of command.com str
MOV BX,OFFSET Parm_block ;ES:BX is adr of parameter block
MOV AX,4b00h ;DOS EXEC sub-task function
INT 21h ;COMMAND.COM now executing user's cmd
; Return from execution of DOS shell - all registers may be corrupted:
MOV AX,CS ;CS is only OK register
MOV ES,AX
MOV DS,AX
MOV SS,AX
MOV SP,OFFSET Stack_top ;Reset stack pointer
JC Handle_Exec_Error ;If DOS EXEC function failed handle it
;-----------------------------------------------------------------------------;
; Now find NEXT (or first) subdirectory below the current one ;
;-----------------------------------------------------------------------------;
Find_another_SubDirectory:
MOV DX,[DTA_Ptr] ;Tell DOS to use different DTA
MOV AH,1Ah ;DOS set DTA function
INT 21h
CMP FF_Flag,First_time ;Is this first time in this directory?
JNE Find_next ; IF not, do a find next
MOV DX,OFFSET Global_str ; Else do an initial find on *.*
MOV CX,Subdirectory_attrib ; find only subdirectories
MOV AH,4Eh ; DOS FIND 1st function
INT 21h
JMP SHORT Validate_directory ;Skip the FIND NEXT function call
Find_Next: ;Find the next directory
MOV AH,4Fh ;DOS find next function
INT 21h
Validate_directory: ;Check that we found valid directory
JC Return_to_Mother ;If find failed, Return to mother dir
MOV DI,[DTA_Ptr] ;Get address of current DTA
; Check the file attribute bits in the DTA (is it a directory or a file?)
TEST BYTE PTR [DI+21],Subdirectory_attrib ;Is this a directory?
JE Find_Next ;If its not a directory keep looking
ADD DI,30 ;Point to directory name in DTA
CMP BYTE PTR [DI],'.' ;IS it a '.' or '..' dir entry?
JE Find_Next ; IF so, ignore it and find next dir
ADD [DTA_Ptr],43 ;Go down one level + use a new DTA
MOV FF_Flag,First_time ;Set flag to do intial *.* dir find
; Change to new daughter directory:
MOV DX,DI ;point to directory to change to
MOV AH,3Bh ;DOS change directory function
INT 21h
JMP SHORT EXEC_Next_Command ;Go execute command in this new Dir
;-----------------------------------------------------------------------------;
; HANDLE EXEC ERROR - Produce specific error messages for the possible DOS ;
; return codes from the EXEC function which may reasonably;
; happen as a result of command or configuration error. ;
;-----------------------------------------------------------------------------;
Handle_Exec_Error: ;Come here if, DOS EXEC func failed
CMP AX,02 ;= file not found/path invalid ?
JNE Handle_Exec_A ; If not, check other codes
MOV DX, OFFSET EXEC_02_Msg ; Else put out appropriate error msg
JMP Error_Exit ; Print error message and terminate
Handle_Exec_A: ;Keep checking other possible codes:
CMP AX,05 ;= Access denied return code?
JNE Handle_Exec_B ; If not, check other codes
MOV DX, OFFSET EXEC_05_Msg ; Else put out appropriate error msg
JMP Error_Exit ; Print error message and terminate
Handle_Exec_B: ;Keep checking other possible codes:
CMP AX,08 ;= Isufficient memory return code?
JNE Unexpected_error ; If not, its an unexpected error..
MOV DX, OFFSET EXEC_08_Msg ; Else put out appropriate error msg
JMP Error_Exit ; Print error message and terminate
Unexpected_error: ;Put out a general catchall error msg
MOV DX,OFFSET XALL_fail_msg ;message for unexpected errors
JMP Error_Exit ; Print error message and terminate
;-----------------------------------------------------------------------------;
; R E T U R N T O M O T H E R - No more files in prior directory so we ;
; return to the previous level and find next;
;-----------------------------------------------------------------------------;
Return_to_Mother: ;Go up one level to mother directory
CMP [DTA_Ptr],OFFSET DTA_Area ;Are we back in original directory?
JNZ Return_to_Prior_Dir ; If not, set directory back 1 level
JMP Normal_termination ; If so, we are all done
Return_to_Prior_Dir:
MOV DX,OFFSET DotDot_str ;Point to ".." string (prev dir)
MOV AH,3Bh ;DOS change dir function
INT 21h ;Change to prior (mother) directory
SUB [DTA_Ptr],43 ;Go back and re-use prior DTA
MOV FF_Flag,Not_first_time ;Set flag so we do a find next rather
; than a find first. (re-use DTA!)
JMP Find_Another_SubDirectory ;Keep checking for DIRs
PAGE
SUBTTL General use subroutines
;***************************************************************************;
;** G e n e r a l U s e S u b r o u t i n e s - start here **;
;***************************************************************************;
;-----------------------------------------------------------------------------;
; Get COMSPEC-search the environment for COMSPEC= string (loc of COMMAND.COM) ;
;-----------------------------------------------------------------------------;
Get_COMSPEC:
MOV ES,WORD PTR [Environment] ;Segment address of Environment
XOR DI,DI ;Start at beginning of segment
MOV SI,OFFSET COMPSEC_str ;Point to "compspec="string
CLD ;Forward direction
XOR AX,AX ;Constant of zero for comparison
Check_Next_ENV_string:
CMP BYTE PTR ES:[DI],0 ;If points to zero, no compspec
JZ Missing_COMSPEC ; FATAL error....
MOV DX,DI ;Save string pointers
MOV BP,SI
MOV CX,8 ;COMSPEC= is 8 characters
REPZ CMPSB ;Check if we are pointing at comspec=
MOV DI,DX ;Restore the pointers
MOV SI,BP
JZ Found_COMSPEC ;We've got a match
MOV CX,200h ;Search for a max of 512 bytes
REPNZ SCASB ;Search for zero byte (AL=0)
JNZ Missing_COMSPEC ; FATAL error....
JMP SHORT Check_Next_ENV_string ;Keep looking for environment strin
Missing_COMSPEC:
MOV DX,OFFSET Missing_CS_MSG ;Message to say comspec= missing
JMP Error_Exit
Found_COMSPEC:
ADD DI,8 ;Point to string after COMSPEC=
MOV WORD PTR [Command_Adr],DI ;Save address: offset
MOV WORD PTR [Command_Adr+2],ES ; and SEGMENT too
RET
;---------------------------------------------------------------;
; Create EXEC Parm block- setup the parameter block for DOS EXEC;
;---------------------------------------------------------------;
Create_EXEC_parm_BLOCK:
MOV [Parm_Block],ES ;Environment segment
MOV [Parm_Block+4],CS ;Segment of parameter
MOV [Parm_Block+8],CS ;Segment of FCB #1
MOV [Parm_Block+12],CS ;Segment of FCB #2
MOV AX,CS ;Point ES back to data segment
MOV ES,AX
RET
;----------------------------------------------------------------------;
; Create Command tail - setup /C followed by user's program to execute ;
; This program is later executed by invokation of COMMAND.COM ;
;----------------------------------------------------------------------;
Create_Command_Tail:
; check program to invoke (parameter at 80h) AKA: PSP parameter
MOV AL,PSP_PARM ;Check # of characters in parameter
OR AL,AL ;Check if no characters (AL=0)
JNZ Parameter_detected ; If a parameter passed..
MOV DX,OFFSET XALL_Help_MSG ;If no input,put out syntax msg
JMP Error_Exit
Parameter_detected:
; Insert a " /C" in front of the PSP parameter
ADD AL,3 ;Increase length by 3 for " /C"
MOV [XALL_Parm],AL ;Store new character count
MOV BYTE PTR[XALL_Parm+1],' ' ;Store blank separator
MOV WORD PTR[XALL_Parm+2],'C/';Store /C (after this is actual parm)
RET
;----------------------------------------------------------------------;
; Display XALL message - Display name of current directory we are ;
; executing the user's command in. ;
;----------------------------------------------------------------------;
Display_XALL_MSG: ;Display name of current directory
MOV DX, offset In_Dir_MSG ;Begining of "Xing in:" message
MOV CX,12 ;message has 12 chars
MOV AH,40h ;DOS Write func
MOV BX,1 ;Handle for std output device
INT 21h ;Write Start message
; Get the current directory string
MOV SI,OFFSET Current_Dir ;Location to store directory string
XOR DX,DX ;Default drive
MOV AH,47h ;DOS Get directory function
INT 21h
; Scan the string in Current_Dir to determine its length:
MOV DI,SI ;Dir string start
MOV DX,SI ;Save a copy for use later
XOR AX,AX ;Scan for zero termination of string
MOV CX,64 ;Scan up to 64 characters
REPNE SCASB ;Find 1st zero byte
SUB DI,DX ;Length of directory string
MOV CX,DI ;Characters to display in dir string
;DX = start of dir strng, CX = # of chars in string
MOV AH,40h ;DOS Write func
INT 21h ;Display the actual directory string
MOV DX,OFFSET CRLF_str ;Prepare to put out carriage ret + LF
MOV CX,2 ;Print 2 characters
MOV AH,40h ;DOS Write func
INT 21h
RET
;---------------------------------------------------------------;
; Error Exit - called with DX pointing to error message to send ;
;---------------------------------------------------------------;
Error_Exit:
MOV AH,09h ;DOS display string function
INT 21h
MOV DX,OFFSET Hit_Key_Msg ;Ask user to hit any key
MOV AH,09h ;DOS display string function
INT 21H
; Wait for user to hit any key
XOR AX,AX
INT 16h ;Wait for user to hit a key
MOV AX,4C20h ;Terminate with 32 errorlevel
INT 21h ;Terminate
Normal_Termination:
; ;Terminate with zero (DOS) errorLEVEL
MOV AX,4C00h
INT 21h
SUBTTL Definition of Data Structures
PAGE
;-----------------------------------------------------------------;
; Data storage definition: ;
;-----------------------------------------------------------------;
Current_Dir LABEL BYTE ;Overlay copyright msg with this
XALL_CR_msg DB 'XALL 1.0 - high speed eXecute ALL subdirectories utility.'
DB CR,LF
DB CR,LF,"MIRDIR 1.0 ",BOX," PCDATA TOOLKIT (c) 1990"
DB " Ziff Communications Co.",CR,LF
DB "PC Magazine ",BOX," Wolfgang Stiller",CR,LF,"$"
XALL_Help_MSG DB CR,LF,'Syntax is: "XALL anyDOScommand"',CR,LF
DB ' "anyDOScommand" will then be eXecuted in the current and '
DB 'all ',CR,LF
DB ' subordinate subdirectories. The program or batch file to'
DB ' be executed',CR,Lf
DB ' must be included in the DOS PATH.$'
Missing_CS_Msg LABEL BYTE ;A message starting with comspec strg
COMPSEC_str DB 'COMSPEC=' ;String in environment to search for
DB ' missing.',CR,LF,'$'
XALL_Fail_msg DB 'XALL failure.',CR,LF
DB 'Probably due to bad COMSPEC - no COMMAND.COM.',CR,LF,'$'
EXEC_02_Msg DB 'Unable to find program.','$'
EXEC_05_Msg DB 'Program access denied.','$'
EXEC_08_Msg DB 'Too little free mem.','$'
Hit_Key_Msg DB CR,LF,LF,'Please hit a key.'
CRLF_Str DB CR,LF,'$'
In_Dir_MSG DB CR,LF,'Xing in: \'
COMMAND_Adr DD 00 ;Full address COMMAND.COM strng in ENV
Global_str DB '*.*',0 ;String for find all files
DotDot_str DB '..',0 ;String to return to mother directory
Parm_Block DW 00 ;Parameter block for DOS EXEC command
DW XALL_PARM,0
DW 5Ch,0
DW 6Ch,0
FF_flag DB 0 ;First Find flag (=0 means find 1st)
DTA_ptr DW DTA_AREA ;Pointer to a 43 char DTA block
DTA_area LABEL BYTE ;area of 32 43 byte DTAs
STACK_Bottom EQU DTA_area+ 32*43 ;Lower limit of the stack
STACK_TOP EQU STACK_Bottom + 80h ;Allocate 128 byte stack
Program_top EQU Stack_top+15 ;End of prog + 15 for paragr rounding
CSEG EndS
END XALL