home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / advos2 / ch09 / whereis.asm < prev    next >
Encoding:
Assembly Source File  |  1988-12-12  |  17.5 KB  |  475 lines

  1.     title    WHEREIS -- File Finder Utility
  2.         page    55,132
  3.         .286
  4.  
  5. ; WHEREIS.ASM
  6. ;
  7. ; A file finder utility that searches the current drive, starting
  8. ; with the root directory (\), for the specified pathname.
  9. ; Wildcard characters can be included.
  10. ;
  11. ; This program requires the modules ARGV.ASM and ARGC.ASM.
  12. ;
  13. ; Assemble with:  C> masm whereis.asm;
  14. ; Link with:  C> link whereis+argv+argc,,,os2,whereis
  15. ;
  16. ; Usage is:  C> whereis pathname
  17. ;
  18. ; Copyright (C) 1988 Ray Duncan
  19. ;
  20.  
  21. stdin   equ     0                       ; standard input handle
  22. stdout  equ     1                       ; standard output handle
  23. stderr  equ     2                       ; standard error handle
  24.  
  25. cr      equ     0dh                     ; ASCII carriage return
  26. lf    equ    0ah            ; ASCII linefeed
  27.  
  28.         extrn   DosChDir:far
  29.         extrn   DosExit:far
  30.         extrn   DosFindClose:far
  31.         extrn   DosFindFirst:far
  32.         extrn   DosFindNext:far
  33.         extrn   DosQCurDir:far
  34.         extrn   DosQCurDisk:far
  35.         extrn   DosSelectDisk:far
  36.         extrn   DosWrite:far
  37.  
  38. _srec    struc                ; search result structure...
  39. cdate   dw      ?                       ; date of creation
  40. ctime   dw      ?                       ; time of creation
  41. adate   dw      ?                       ; date of last access
  42. atime   dw      ?                       ; time of last access
  43. wdate   dw      ?                       ; date of last write
  44. wtime   dw      ?                       ; time of last write
  45. fsize   dd      ?                       ; file size
  46. falloc  dd      ?                       ; file allocation
  47. fattr   dw      ?                       ; file attribute
  48. fcount  db      ?                       ; filename count byte
  49. fname   db      13 dup (?)              ; ASCIIZ filename
  50. _srec   ends
  51.  
  52.  
  53. DGROUP  group   _DATA
  54.  
  55. _DATA   segment word public 'DATA'
  56.  
  57. root    db      '\',0                   ; name of root directory
  58.  
  59. parent  db      '..',0                  ; alias for parent directory
  60.  
  61. wild    db      '*.*',0                 ; matches all files
  62.  
  63. sname   db      64 dup (0)              ; filename for search
  64.  
  65. drvno   dw      0                       ; current drive
  66. drvmap  dd      0                       ; logical drive bitmap
  67.  
  68. dname   db      'X:\'                   ; current drive ID
  69. dbuf    db      80 dup (?)              ; current directory 
  70. dbuf_len dw     ?                       ; length of buffer
  71.  
  72. sbuf    _srec   <>                      ; receives search results
  73. sbuf_len equ $-sbuf
  74.  
  75. count   dw      0                       ; total files matched
  76. wlen    dw      ?                       ; receives bytes written
  77. shandle dw      -1                      ; directory search handle
  78. scount    dw    1            ; number of files to return
  79.  
  80. msg1    db      cr,lf
  81.         db      'whereis: no files found'
  82.         db      cr,lf
  83. msg1_len equ $-msg1
  84.  
  85. msg2    db      cr,lf
  86. msg2_len equ $-msg2
  87.  
  88. msg3    db      cr,lf
  89.     db    'whereis: missing filename'
  90.         db      cr,lf
  91. msg3_len equ $-msg3
  92.  
  93. msg4    db      cr,lf
  94.         db      'whereis: bad drive'
  95.         db      cr,lf
  96. msg4_len equ $-msg4
  97.  
  98. _DATA   ends
  99.  
  100.  
  101. _TEXT   segment word public 'CODE'
  102.  
  103.         assume  cs:_TEXT,ds:DGROUP
  104.  
  105.         extrn   argv:near
  106.         extrn   argc:near
  107.  
  108. whereis proc    far
  109.  
  110.         call    argc                    ; filename present in 
  111.         cmp     ax,2                    ; command tail?
  112.         jae     where1                  ; jump, filename present
  113.  
  114.                                         ; no filename, exit...
  115.         mov     dx,offset DGROUP:msg3   ; error message address
  116.         mov     cx,msg3_len             ; message length
  117.         jmp     where6                  ; go terminate
  118.  
  119. where1:                                 ; get current drive... 
  120.         push    ds                      ; receives drive code
  121.         push    offset DGROUP:drvno
  122.         push    ds                      ; receives drive bitmap
  123.         push    offset DGROUP:drvmap
  124.         call    DosQCurDisk             ; transfer to OS/2
  125.  
  126.         mov     ax,1                    ; get address and length
  127.         call    argv                    ; of filename parameter
  128.                                         ; returns ES:BX = address
  129.                                         ;         AX    = length
  130.         mov     cx,ax                   ; save length in CX     
  131.  
  132.         cmp     ax,2                    ; parameter length > 2?
  133.         jle     where3                  ; no, jump
  134.         cmp     byte ptr es:[bx+1],':'  ; drive delimiter present?
  135.         jne     where3                  ; no, jump
  136.  
  137.         mov     al,es:[bx]              ; get ASCII drive code
  138.     or    al,20h            ; fold to lowercase
  139.         xor     ah,ah
  140.         sub     ax,'a'-1                ; convert drive code to
  141.         mov     drvno,ax                ; binary and save it
  142.     cmp    ax,1            ; make sure drive valid
  143.         jb      where2                  ; jump, bad drive
  144.         cmp     ax,26
  145.         ja      where2                  ; jump, bad drive
  146.  
  147.         add     bx,2                    ; advance command tail
  148.         sub     cx,2                    ; pointer past drive code
  149.  
  150.                                         ; set drive for search...
  151.         push    ax                      ; drive code
  152.         call    DosSelectDisk           ; transfer to OS/2
  153.         or      ax,ax                   ; drive OK?
  154.         jz      where3                  ; jump, drive was valid
  155.  
  156.                                         ; bad drive, exit...
  157. where2: mov     dx,offset DGROUP:msg4   ; error message address
  158.         mov     cx,msg4_len             ; message length
  159.         jmp     where6
  160.  
  161. where3: mov     di,offset DGROUP:sname  ; DS:DI = local buffer
  162.  
  163. where4: mov     al,es:[bx]              ; copy filename to local
  164.         mov     [di],al                 ; buffer byte by byte...
  165.         inc     di
  166.         inc     bx
  167.         loop    where4
  168.  
  169.         mov     byte ptr [di],0         ; append null byte
  170.  
  171.         push    ds                      ; make DGROUP addressable       
  172.         pop     es                      ; with ES
  173.         assume  es:DGROUP
  174.  
  175.         mov     dx,offset DGROUP:root   ; start searching with 
  176.         call    schdir                  ; the root directory
  177.  
  178.         cmp     count,0                 ; any matching files found?
  179.         jne     where5                  ; yes, exit silently
  180.  
  181.                     ; no, display 'no files'...
  182.         push    stdout                  ; standard output handle
  183.         push    ds                      ; message address
  184.         push    offset DGROUP:msg1
  185.         push    msg1_len                ; message length
  186.         push    ds                      ; receives bytes written
  187.         push    offset DGROUP:wlen
  188.         call    DosWrite                ; transfer to OS/2
  189.  
  190. where5:                                 ; final exit to OS/2...
  191.         push    1                       ; terminate all threads
  192.     push    0            ; return code = 0 (success)
  193.         call    DosExit                 ; transfer to OS/2
  194.  
  195. where6:                                 ; common error exit...
  196.                                         ; DS:DX = msg, CX = length
  197.         push    stderr                  ; standard output handle
  198.         push    ds                      ; address of message
  199.         push    dx
  200.         push    cx                      ; length of message
  201.         push    ds                      ; receives bytes written
  202.         push    offset DGROUP:wlen
  203.         call    DosWrite                ; transfer to OS/2
  204.  
  205.                                         ; final exit to OS/2...
  206.         push    1                       ; terminate all threads
  207.         push    1                       ; exit code = 1 (error)
  208.         call    DosExit                 ; transfer to OS/2
  209.  
  210. whereis endp
  211.  
  212.  
  213. ; SCHDIR:       search a directory for matching
  214. ;               files and any other directories
  215. ;
  216. ; Call with:    DS:DX = ASCIIZ directory name
  217. ; Returns:      nothing
  218. ; Uses:         all registers
  219.  
  220. schdir  proc    near
  221.  
  222.         push    shandle                 ; save old search handle
  223.         mov     shandle,-1              ; initialize search handle
  224.  
  225.                                         ; set search directory...
  226.         push    ds                      ; directory name address
  227.         push    dx
  228.         push    0                       ; reserved DWORD 0
  229.         push    0
  230.         call    DosChDir                ; transfer to OS/2
  231.  
  232.         call    schfile                 ; search current directory
  233.                                         ; for matching files
  234.  
  235.                                         ; search for directories
  236.         mov     scount,1                ; max matches to return
  237.         push    ds                      ; target name address
  238.         push    offset DGROUP:wild
  239.         push    ds                      ; receives search handle
  240.         push    offset DGROUP:shandle
  241.     push    10h            ; normal + dir attribute
  242.         push    ds                      ; result buffer address
  243.         push    offset DGROUP:sbuf
  244.         push    sbuf_len                ; result buffer length
  245.         push    ds                      ; receives match count
  246.         push    offset DGROUP:scount                    
  247.         push    0                       ; reserved DWORD 0
  248.         push    0
  249.         call    DosFindFirst            ; transfer to OS/2
  250.  
  251.         or      ax,ax                   ; find anything?
  252.         jnz     schdir3                 ; no, jump
  253.  
  254. schdir1:                                ; found some match...
  255.         test    sbuf.fattr,10h          ; is it a directory?
  256.         jz      schdir2                 ; no, skip it
  257.  
  258.         cmp     sbuf.fname,'.'          ; is it . or .. entry?
  259.         je      schdir2                 ; yes, skip it
  260.  
  261.                                         ; no, new directory found
  262.         mov     dx,offset DGROUP:sbuf.fname
  263.         call    schdir                  ; call self to search it
  264.  
  265.                                         ; restore old directory...
  266.         push    ds                      ; address of '..' alias
  267.         push    offset DGROUP:parent
  268.         push    0                       ; reserved DWORD 0
  269.         push    0
  270.         call    DosChDir                ; transfer to OS/2
  271.  
  272. schdir2:                                ; found at least one match,
  273.                                         ; look for next match...
  274.         mov     scount,1                ; max matches to return
  275.         push    shandle                 ; handle from DosFindFirst
  276.         push    ds                      ; result buffer address
  277.         push    offset DGROUP:sbuf
  278.         push    sbuf_len                ; result buffer length
  279.         push    ds                      ; receives match count
  280.         push    offset DGROUP:scount                    
  281.         call    DosFindNext             ; transfer to OS/2
  282.  
  283.         or      ax,ax                   ; any matches found?
  284.         jz      schdir1                 ; yes, go process it
  285.  
  286. schdir3:                                ; end of search...
  287.         push    shandle                 ; close search handle
  288.         call    DosFindClose            ; transfer to OS/2
  289.  
  290.         pop     shandle                 ; restore previous handle
  291.  
  292.         ret                             ; back to caller
  293.  
  294. schdir  endp
  295.  
  296.  
  297. ; SCHFILE:      search current directory for
  298. ;               files matching string in 'sname'
  299. ;
  300. ; Call with:    nothing
  301. ; Returns:      nothing
  302. ; Uses:         all registers
  303.  
  304. schfile proc    near
  305.  
  306.         push    shandle                 ; save previous handle
  307.         mov     shandle,-1              ; initialize search handle
  308.  
  309.         mov     scount,1                ; max matches to return
  310.         push    ds                      ; name to match
  311.         push    offset DGROUP:sname
  312.         push    ds                      ; receives search handle
  313.         push    offset DGROUP:shandle
  314.         push    0h                      ; attribute=normal files
  315.         push    ds                      ; result buffer address
  316.         push    offset DGROUP:sbuf
  317.         push    sbuf_len                ; result buffer length
  318.         push    ds                      ; receives match count
  319.         push    offset DGROUP:scount                    
  320.         push    0                       ; reserved DWORD 0
  321.         push    0
  322.         call    DosFindFirst            ; transfer to OS/2
  323.  
  324.         or      ax,ax                   ; any matches found?
  325.         jnz     schfile3                ; no, terminate search
  326.  
  327. schfile1:                               ; found matching file...
  328.         call    pfile                   ; display its name
  329.  
  330.                                         ; look for next match...
  331.         push    shandle                 ; handle from DosFindFirst
  332.         push    ds                      ; result buffer address
  333.         push    offset DGROUP:sbuf
  334.         push    sbuf_len                ; result buffer length
  335.         push    ds                      ; receives match count
  336.         push    offset DGROUP:scount                    
  337.         call    DosFindNext             ; transfer to OS/2
  338.  
  339.         or      ax,ax                   ; any more matches?
  340.         jz      schfile1                ; yes, go display filename
  341.  
  342. schfile3:                               ; end of search...
  343.         push    shandle                 ; close search handle
  344.         call    DosFindClose            ; transfer to OS/2      
  345.  
  346.         pop     shandle                 ; restore previous handle
  347.         ret                             ; return to caller
  348.  
  349. schfile endp
  350.  
  351.  
  352. ; PFILE:        display current drive and directory,
  353. ;               followed by filename from 'sbuf.fname'
  354. ;
  355. ; Call with:    nothing
  356. ; Returns:      nothing
  357. ; Uses:         all registers
  358.  
  359. pfile   proc    near
  360.  
  361.         inc     count                   ; count matched files
  362.  
  363.         call    pdir                    ; display drive:path
  364.  
  365.                                         ; fold name to lower case
  366.         mov     bx,offset DGROUP:sbuf.fname
  367.         call    makelc
  368.  
  369.                                         ; display filename...
  370.         push    stdout                  ; standard output handle
  371.         push    ds                      ; filename address
  372.         push    offset DGROUP:sbuf.fname
  373.         mov     al,sbuf.fcount          ; filename length
  374.         xor     ah,ah
  375.         push    ax
  376.         push    ds                      ; receives bytes written
  377.         push    offset DGROUP:wlen
  378.         call    DosWrite                ; transfer to OS/2
  379.  
  380.                                         ; send newline sequence...
  381.         push    stdout                  ; standard output handle
  382.         push    ds                      ; address of newline
  383.         push    offset DGROUP:msg2
  384.         push    msg2_len                ; length of newline
  385.         push    ds                      ; receives bytes written
  386.         push    offset DGROUP:wlen
  387.         call    DosWrite                ; transfer to OS/2
  388.  
  389.         ret                             ; return to caller
  390.  
  391. pfile   endp
  392.  
  393.  
  394. ; PDIR:         display current drive and directory
  395. ;
  396. ; Call with:    nothing
  397. ; Returns:      nothing
  398. ; Uses:         AX, BX, CX, DI, ES
  399.  
  400. pdir    proc    near
  401.  
  402.         mov     ax,drvno                ; convert binary drive 
  403.         add     al,'A'-1                ; code to ASCII drive 
  404.         mov     dname,al                ; and store it for output       
  405.  
  406.         mov     dbuf_len,dbuf_len-dbuf  ; initialize length of
  407.                                         ; directory buffer
  408.  
  409.                                         ; get current directory...
  410.         push    0                       ; drive 0 = default 
  411.         push    ds                      ; receives ASCIIZ path
  412.         push    offset DGROUP:dbuf
  413.         push    ds                      ; contains buffer length
  414.         push    offset DGROUP:dbuf_len
  415.         call    DosQCurDir              ; transfer to OS/2
  416.         
  417.         mov     di,offset DGROUP:dbuf   ; address of path
  418.  
  419.         cmp     byte ptr [di],0         ; is path = root?       
  420.         je      pdir1                   ; yes, jump
  421.  
  422.         mov     cx,dbuf_len-dbuf        ; no, scan for null 
  423.         xor     al,al                   ; byte at end of path...
  424.         repne scasb
  425.  
  426.         mov     byte ptr [di-1],'\'     ; append a backslash
  427.  
  428. pdir1:  mov     bx,offset DGROUP:dname  ; fold everything to
  429.     call    makelc            ; lowercase
  430.  
  431.                                         ; now display drive:path...
  432.         push    stdout                  ; standard output handle
  433.         push    ds                      ; address of pathname
  434.         push    offset DGROUP:dname
  435.     sub    di,offset DGROUP:dname    ; length of drive and path
  436.         push    di
  437.         push    ds                      ; receives bytes written
  438.         push    offset DGROUP:wlen
  439.         call    DosWrite                ; transfer to OS/2
  440.  
  441.         ret                             ; back to caller
  442.  
  443. pdir    endp
  444.  
  445.  
  446. ; MAKELC:    convert ASCIIZ string to lowercase
  447. ;
  448. ; Call with:    DS:BX = string address
  449. ; Returns:      nothing
  450. ; Uses:         BX
  451.  
  452. makelc  proc    near
  453.         
  454. make1:  cmp     byte ptr [bx],0         ; end of string?
  455.         je      make3                   ; jump if end
  456.  
  457.         cmp     byte ptr [bx],'A'       ; check next character
  458.     jb    make2            ; jump, not uppercase
  459.         cmp     byte ptr [bx],'Z'
  460.     ja    make2            ; jump, not uppercase
  461.  
  462.     or    byte ptr [bx],20h    ; fold to lowercase
  463.  
  464. make2:  inc     bx                      ; advance through string
  465.         jmp     make1
  466.  
  467. make3:  ret                             ; back to caller
  468.  
  469. makelc  endp
  470.  
  471. _TEXT   ends
  472.  
  473.         end     whereis
  474.