TITLE WHEREIS - FIND A FILE ON THE DRIVE
PAGE 60,132
CGROUP  GROUP   CODSEG, DATSEG
        ASSUME  CS:CGROUP,DS:CGROUP
DTA     STRUC
        RESERVED        DB      21 DUP(?)
        ATTRIBUTE       DB
        TIME            DW
        DATE            DW
        SIZE            DD
        NAMFOUND      DB      13 DUP(?)
DTA     ENDS

DATSEG SEGMENT        PUBLIC
STANAME       DB      '*.*',0
PATNAME       DB      '\',0
                DB      80 DUP (0)      ; SPACE FOR 64 CHAR PATH NAME
                                        ; AND 13 CHAR FILE NAME
FILNAME       DB      13 DUP (0)      ; SAVE ROOM FOR FULL DOS NAME
DISTRANSFEAREAS     LABEL   BYTE    ; THIS STARTS AT THE END OF THE WHEREIS
DATSEG        ENDS
PAGE
;---------------------------------------------------------------------;
;  THIS IS THE MAIN PROGRAM THAT SETS UP THE INITIAL CONDITIONS FOR   ;
; SEARCDIRECTORY WHICH, IN TURN, DOES A RECURSIVE SEARCH.           ;
;                                                                     ;
; READS: PATNAME                                            ;
; WRITES: FILNAME                                           ;
; CALLS: SEARCDIRECTORY                                     ;
;---------------------------------------------------------------------;
CODSEG        SEGMENT
        ORG     100H
WHEREIS         PROC    NEAR
        MOV     SI,82H                  ; START OF COMMAND LINE
        MOV     DI,OFFSET CGROUP:FILNAME
GESEARCNAME:
        LODSB                           ; GET FIRST CHARACTER
        CMP     AL,0DH                  ; CARRIAGE RETURN CHARACTER?
        JE      DONREADINNAME       ; YES, END OF NAME
        STOSB
        JMP     GESEARCNAME
DONREADINNAME:
        XOR     AL,AL                   ; WRITE A 0 AT THE END
        STOSB
        MOV     DI,OFFSET CGROUP:PATNAME
        XOR     AL,AL                   ; SEARCH DIRECTORY FOR THE ZERO AT THE END
        CLD                             ; OF PATNAME
        MOV     CX,64                   ; MAX. LENGTH OF SCAN FOR 0
        REPNZ   SCASB
        MOV     BX,DI
        DEC     BX                      ; DS:BX POINTS TO THE END OF PATNAME
        MOV     DX,0                    ; TELL SEARCH DIRECTORY THIS IS FIRST
        CALL    SEARCDIRECTORY        ; NOW DO THE RECURSIVE SEARCH
        INT     20H                     ; ALL DONE RETURN TO DOS
WHEREIS ENDP
PAGE
;----------------------------------------------------------------;
;  THIS PROCEDURE SEARCHES ALL THE FILES IN THE CURRENT DIRECTORY;
;LOOKING FOR A MATCH. IT ALSO PRINTS THE FULL NAME OF EACH MATCH ;
;                                                                ;
;       DS:BX   POINTER TO END OF CURRENT PATH NAME.             ;
;       DS:DX   OLD DISK TRANSFER AREA (DTA).                    ;
;                                                                ;
{; READS:        DISK TRANSFER AREA                               ;
; WRITES: DISK TRANSFER AREA                             ;
; CALLS: BUILNAME,GEFIRSMATCH,                     ;
;               WRITMATCHENAME,GENEXMATCH                ;
;               BUILSTANAME,SEARCSUDIRECTORY             ;
;----------------------------------------------------------------;
SEARCDIRECTORY        PROC    NEAR
        PUSH    SI                      ; NEED TO RESTORE ON EXIT
        PUSH    DX
        CALL    BUILNAME              ; BUILD THE ABSOLUTE SEARCH NAME
        CALL    GEFIRSMATCH         ; SEE IF THERE IS A MATCH THERE
        JC      NMATCH                ; NO MATCH CHECK SUB DIRECTORIES
        CALL    WRITMATCHENAME      ; WRITE NAME OF MATCH
FINNEXFILE:
        CALL    GENEXMATCH          ; FIND THE NEXT MATCH
        JC      NMATCH                ; NO MATCH CHECK SUB DIRECTORIES
        CALL    WRITMATCHENAME      ; WRITE NAME OF MATCH
        JMP     FINNEXFILE          ; LOOK FOR NEXT MATCHING NAME
NMATCH:
        POP     DX                      ; RESTORE DTA
        PUSH    DX
        CALL    BUILSTANAME         ; SEARCH FOR ALL DIRECTORIES
        CALL    GEFIRSMATCH         ; GET FIRST ENTRY
        JC      NMORMATCHES         ; THERE ARE NO ENTRIES
        MOV     SI,DX                   ; PUT ADDRESS OF DTA IN SI
        TEST    [SI].ATTRIBUTE,10H      ; IS IT A DIRECTORY ?
        JNZ     IDIRECTORY            ; YES, THEN SEARCH DIRECTORY
FINNEXDIRECTORY:
        CALL    GENEXMATCH          ; NO, THEN FIND THE NEXT MATCH
        JC      NMORMATCHES         ; THERE ARE NO MORE ENTRIES
        TEST    [SI].ATTRIBUTE,10H      ; IS IT A DIRECTORY ?
        JZ      FINNEXDIRECTORY     ; YES, SEARCH DIRECTORY
IDIRECTORY:
        CMP     [SI].NAMFOUND,'.'     ; IS THIS A . OR .. DIRECTORY
        JE      FINNEXDIRECTORY     ; YES THEN SKIP TO NEXT DIRECTORY
        CALL    SEARCSUDIRECTORY    ; SEARCH THE SUB DIR
        PUSH    AX                      ; NOW RESET THE DTA
        MOV     AH,1AH
        INT     21H
        POP     AX
        JMP     FINNEXDIRECTORY
NMORMATCHES:
        POP     DX
        POP     SI
        RET
SEARCDIRECTORY        ENDP
PAGE
;---------------------------------------------------------------;
; THIS PROCEDURE SEARCHES THE SUB DIR WHOSE NAME IS IN THE DTA  ;
;                                                               ;
;       DS:BX   END OF CURRENT PATHNAME                         ;
;       DS:[DX].NAMFOUND      NAME OF SUB DIR TO SEARCH ;
;                                                               ;
; READS:        PATNAME                                       ;
; WRITE:        PATNAME                                       ;
; CALLS:        SEARCDIRECTORY                                ;
;--------------------------------------------------------------;
SEARCSUDIRECTORY    PROC    NEAR
        PUSH    DI
        PUSH    SI
        PUSH    AX
        PUSH    BX
        CLD                             ; SET FOR INCREMENT
        MOV     SI,DX                   ; PUT THE ADDRESS OF DTA IN SI
        ADD     SI,OFFSET NAMFOUND    ; SET TO START OF SUB DIR NAME
        MOV     DI,BX                   ; DS:DI - 0 AT END OF PATH NAME
COPLOOP:
        LODSB                           ; COPY ONE CHARACTER
        STOSB
        OR      AL,AL                   ; WAS IT A ZERO
        JNZ     COPLOOP               ; NO, KEEP COPYING
        MOV     BX,DI                   ; SET BX TO END OF NEW PATHNAME
        STD                             ; SET FLAG FOR DECREMENT
        STOSB                           ; STORE A 0 AT END OF STRING
        MOV     AL,'\'
        STOSB                           ; PLACE A \ AT END OF PATHNAME
        CALL    SEARCDIRECTORY        ; SEARCH THIS NEW PATH
        POP     BX                      ; RESTORE THE OLD END-OF-PATH
        MOV     BYTE PTR [BX],0         ; AND STORE A ZERO THERE
        POP     AX
        POP     SI
        POP     DI
        RET
SEARCSUDIRECTORY    ENDP
PAGE
;---------------------------------------------------------------;
;  THIS PROCEDURE PRINTS THE MATCHED NAME AFTER THE PATH NAME   ;
;                                                               ;
;       DS:DX   POINTER TO CURRENT DTA                          ;
;                                                               ;
; READS:        PATNAME,NAMFOUND (IN DTA)                   ;
; CALLS: WRITSTRING,SENCRLF                         ;
;---------------------------------------------------------------;
WRITMATCHENAME      PROC    NEAR
        PUSH    AX
        PUSH    DX
        MOV     DX,OFFSET CGROUP:PATNAME
        MOV     AL,[BX]                 ; SAVE CHAR AT END OF PATH
        MOV     BYTE PTR [BX],0         ; SET FOR END OF STRING
        CALL    WRITSTRING
        MOV     [BX],AL                 ; RESTORE CHARACTER
        POP     DX
        PUSH    DX
        ADD     DX,OFFSET NAMFOUND
        CALL    WRITSTRING
        CALL    SENCRLF
        POP     DX
        POP     AX
        RET
WRITMATCHENAME      ENDP
PAGE
;---------------------------------------------------------------;
;  THIS PROCEDURE BUILDS AN ABSOLUTE SEARCH NAME FROM PATNAME ;
; FOLLOWED BY FILNAME                                         ;
;                                                               ;
; READS:        FILNAME                                       ;
; CALLS:        BUILD                                           ;
;---------------------------------------------------------------;
BUILNAME      PROC    NEAR
        PUSH    SI
        MOV     SI,OFFSET CGROUP:FILNAME
        CALL    BUILD
        POP     SI
        RET
BUILNAME      ENDP
BUILSTANAME PROC    NEAR
        PUSH    SI
        MOV     SI,OFFSET CGROUP:STANAME
        CALL    BUILD
        POP     SI
        RET
BUILSTANAME ENDP
PAGE
;---------------------------------------------------------------;
;  THIS PROCEDURE APPEND THE STRING AT DS:SI TO PATNAME IN    ;
; PATNAME. IT KNOWS WHERE THE PATNAME END FROM KNOWING HOW  ;
; LONG PATNAME IS.                                            ;
;                                                               ;
;       DS:SI   NAME OF FILE                                    ;
;       DS:BX   END OF PATNAME                                ;
;                                                               ;
; READS:        DS:SI                                           ;
; WRITES:       PATNAME                                       ;
;---------------------------------------------------------------;
BUILD   PROC    NEAR
        PUSH    AX
        PUSH    DI
        MOV     DI,BX
        CLD                             ; SET FOR INCREMENT
COPNAME:
        LODSB
        STOSB                           ; COPY A CHARACTER OF NAME
        OR      AL,AL                   ; END OF STRING YET?
        JNZ     COPNAME               ; NO KEEP COPYING
        POP     DI
        POP     AX
        RET
BUILD   ENDP
PAGE
;------------------------------------------------------------------;
;  THIS PROCEDURE FINDS THE FIRST MATCH BETWEEN THE NAME GIVEN BY  ;
; DS:DX AND THE DIRECTORY ENTRIES FOUND IN THE DIRECTORY PATNAME ;
;                                                          ;
;       DS:DX   POINTER TO CURRENT DTA                             ;
;RETURNS:                                                          ;
;       CF      0       A MATCH WAS FOUND                          ;
;               1       NO MATCH FOUND                     ;
;       AX      2      FILE NOT FOUND                             ;
;               18      NO MORE FILES                              ;
;       DS:DX           POINTER TO NEW DTA                         ;
;                                                                  ;
; READS:        PATNAME                                          ;
; WRITES:       DISTRANSFEAREAS                                ;
;------------------------------------------------------------------;
GEFIRSMATCH PROC    NEAR
        PUSH    CX
        CMP     DX,0            ; FIRST ONE :
        JA      ALLOCATE        ; NO THEN ALLOCATE SPACE
        MOV     DX,OFFSET CGROUP:DISTRANSFEAREAS-TYPE DTA
ALLOCATE:
        ADD     DX,TYPE DTA     ; NO THEN ALLOCATE ROOM FOR NEW DTA
        MOV     CX,10H          ; SEARCH ATTRIBUTE FOR FILES ANDS DIRS.
        MOV     AH,1AH          ; SET DTA
        INT     21H
        PUSH    DX              ; NEED DX FOR ADDRESS OF SEARCH NAME
        MOV     DX,OFFSET CGROUP:PATNAME
        MOV     AH,4EH          ; CALL FOR FIND FIRST MATCH
        INT     21H
        POP     DX
        POP     CX
        RET
GEFIRSMATCH ENDP
PAGE
;---------------------------------------------------------------;
; THIS PROCEDURE IS MUCH LIKE GET FIRST MATCH.                  ;
;                                                               ;
; RETURNS                                                       ;
;       CF      0       A MATCH WAS FOUND                       ;
;               1       NO MATCH FOUND                          ;
;       AX      2       FILE NOT FOUND                          ;
;               18      NO MORE FILES                           ;
;                                                               ;
; READS:        PATNAME                                       ;
; WRITES:       DISTRANSFEAREAS                             ;
;---------------------------------------------------------------;
GENEXMATCH  PROC    NEAR
        PUSH    CX
        PUSH    DX
        MOV     DX,OFFSET CGROUP:PATNAME
        MOV     CX,10H          ;ATTRIBUTE FOR FILES AND DIRECTORIES
        MOV     AH,4FH          ; CALL FOR FIND NEXT MATCH
        INT     21H
        POP     DX
        POP     CX
        RET
GENEXMATCH  ENDP
PAGE
;---------------------------------------------------------------;
; THIS PROC SEND A CRLF TO THE SCREEN                           ;
;---------------------------------------------------------------;
SENCRLF       PROC    NEAR
        PUSH    AX
        PUSH    DX
        MOV     AH,02
        MOV     DL,0AH
        INT     21H
        MOV     DL,0DH
        INT     21H
        POP     DX
        POP     AX
        RET
SENCRLF       ENDP
;---------------------------------------------------------------;
; THIS PROC WRITES THE ASCIIZ STRING AT                         ;
; DS:DX         ADDRESS OF ASCIIZ                               ;
;---------------------------------------------------------------;
WRITSTRING    PROC    NEAR
        PUSH    AX
        PUSH    DX
        PUSH    SI
        CLD                             ; SET FOR INCREMENT
        MOV     SI,DX                   ; SET POINTER TO STRING
        MOV     AH,2
       LODSB
WRITSTRINLOOP:
        MOV     DL,AL
        INT     21H                     ; WRITE THE CHAR
        LODSB
        OR      AL,AL                   ; ENOF STRING??
        JNZ     WRITSTRINLOOP
        POP     SI
        POP     DX
        POP     AX
        RET
WRITSTRING    ENDP
;
CODSEG        ENDS
        END     WHEREIS
 