home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / misc_programming / battutor.l!h / FINDFILE.ASM < prev    next >
Assembly Source File  |  1990-11-02  |  14KB  |  297 lines

  1.                PAGE 60,132
  2. TITLE  FINDFILE.COM  VER.2.0  14-AUG-83  19:15
  3. comment *
  4.  
  5.                         FINDFILE.COM
  6.  
  7.  
  8.         VERSION 2.0     14-AUG-83
  9.  
  10.         Written by      Warren Craycroft
  11.                         6236 Oakdale Ave.
  12.                         Oakland, CA  94605
  13.  
  14.  
  15.         (C)  1983  by Warren Craycroft.  Permission is granted to copy and
  16.         distribute this program, including source code, provided that no
  17.         charge shall be made except for a reasonable charge for the media
  18.         and handling, and that this notice shall remain intact in all copies.
  19.  
  20.  
  21. *
  22. comment *
  23.         This program is a utility that can be used with DOS 2.0 to
  24.         find the disk drive number that contains a certain file.
  25.  
  26.         A common use of FINDFILE is to help a batch file "orient"
  27.         itself by discovering on which drive the Batch File itself is
  28.         running, and on what drives other files (such as useful system
  29.         utilities) can be found.  A lot of this orientation can be done
  30.         without bothering or confusing the user with a lot of questions
  31.         or constraints in locating disks in certain drives.
  32.  
  33.         A key feature of this search (and where this method of orien-
  34.         tation differs from the use of PATH or IF EXIST ) is that
  35.         searching on the disk drives is done "benignly".  By this we mean
  36.         that FINDFILE doesn't come to a grinding halt if an empty
  37.         disk drive is searched.  Instead, it continues the search on
  38.         the rest of the drives.  This further relieves the user from
  39.         having to locate certain disks on certain drives.  The target
  40.         file may be on the B: or C: drive with the A: drive empty, and
  41.         FINDFILE will find it without the annoying "ignore, abort, retry"
  42.         message.  If the file is not found, then you may gently prod the
  43.         user to place the required disk "in any drive" and try again.
  44.  
  45.         The syntax of the command line is the following:
  46.  
  47.                 findfile  fname
  48.  
  49.         where fname is a standard DOS path, filename, and extention.
  50.         If you include a drive specification (like "a:" for example),
  51.         the drive spec will be ignored by FINDFILE.
  52.  
  53.         FINDFILE benignly searches all disk drives that  are claimed
  54.         to present by the system board switches, in order A:, B:, C:, and
  55.         D:.  If the file is found, the disk number of the first disk on
  56.         which it was found is returned in errorlevel and may be tested
  57.         by a Batch File IF Subcommand.
  58.  
  59.  
  60.                 If fname found:         errorlev = 0 if fname on A:
  61.                                         errorlev = 1 if fname on B:
  62.                                         errorlev = 2 if fname on C:
  63.                                         errorlev = 3 if fname on D:
  64.  
  65.                 If fname not found:     errorlev = 255
  66.  
  67.                 If fname is missing:    errorlev = 255 , and a CNTRL BREAK
  68.                                                    halts the Batch File
  69.  
  70. *
  71. ;
  72. ;               constant equates
  73. ;
  74. BEL_CHAR        EQU     07              ;ascii BEL keycode
  75. CR              EQU     0DH             ;ascii carriage return
  76. LF              EQU     0AH             ;ascii line feed
  77. TAB_CHAR        EQU     09              ;ascii tab
  78. BLANK_CHAR      EQU     ' '             ;ascii blank
  79. COLON_CHAR      EQU     ':'             ;ascii colon
  80. NOT_FOUND_CODE  EQU     255             ;errorlev returned for fname not
  81.                                         ;found
  82. DISK_MASK       EQU     00C0H           ;mask for equipment word's disk
  83.                                         ;count field
  84. ;
  85. ;
  86. ;       declare a relocatable segment.  Follow the .COM file requirements
  87. ;       of entry point at 100H and making all seg register references relative
  88. ;       to CS (no relocatable values MOV'ed into segment registers).
  89. ;
  90. ;
  91. COM_CODE      SEGMENT
  92. ;
  93.                 ORG     80H             ;PSP offset 80:  user's command line
  94. PSP_CMD_LINE    LABEL   BYTE            ;define a label for address refs
  95. ;
  96.                 ORG     100H            ;for COM file
  97. ;
  98. ;
  99.                 ASSUME  CS:COM_CODE,DS:COM_CODE    ;tell assembler value of CS
  100.                 ASSUME  ES:COM_CODE                ; DS, and ES
  101. ;
  102. ;
  103. START           PROC            FAR     ;FAR is meaningless; no RETS
  104. ;
  105.                 MOV     SI,OFFSET PSP_CMD_LINE  ;offset of user's cmd line
  106.                 SUB     CX,CX                   ;clear CX
  107.                 MOV     CL,[SI]                 ;byte count of line
  108.                 OR      CL,CL                   ;zero?
  109.                 JZ      NO_FNAME                ;jump if yes, no fname param
  110.                 SUB     BX,BX                   ;else zero index
  111. ;
  112. ;       find first non-blank or non-tab character of command line
  113. ;
  114. STRIP_BLANKS:   INC     SI                      ;point to next char
  115.                 MOV     AL,[SI]                 ;get next char from cmd line
  116.                 CMP     AL,BLANK_CHAR           ;is it blank?
  117.                 JE      LOOP_BLANKS             ;jump if yes, keep looking
  118.                 CMP     AL,TAB_CHAR             ;is it a tab?
  119.                 JNE     GOT_NON_BLANK           ;jump if not, first non-blank
  120. LOOP_BLANKS:    LOOP    STRIP_BLANKS            ;else keep looking
  121. ;
  122. ;       fname is missing from command line (all blanks or tabs, or else
  123. ;       zero characters on line
  124. ;
  125. NO_FNAME:       MOV     DX,OFFSET ERROR_MESSAGE ;adr offset of error message
  126.                 MOV     AH,9                    ;DOS fn call, "print string"
  127.                 INT     21H                     ;call DOS
  128.                 INT     23H                     ;cause a control break, cause
  129.                                                 ;this is probably a bug in
  130.                                                 ;batch file creation.
  131.                 JMP     NO_FILE_EXIT            ;then exit with errorlevel =
  132.                                                 ; "NOT_FOUND_CODE"
  133. ;
  134. ;       found first non-blank/tab character on command line
  135. ;       at [SI][BX] .  Check for disk designator " n: " and
  136. ;       "strip" it from string by moving up pointer and decreasing
  137. ;       remaining bytes count.
  138. ;
  139. GOT_NON_BLANK:  CMP     BYTE PTR [SI+1],COLON_CHAR  ;2nd non-blank char ":"?
  140.                 JNE     ADD_DRIVE               ;if not, [SI] is start of strng
  141.                 INC     SI                      ;else strip off the drive spec
  142.                 INC     SI
  143.                 DEC     CX                      ;and decr remaining byte count
  144.                 JZ      NO_FNAME                ;if string hits zero bytes left,
  145.                 DEC     CX
  146.                 JZ      NO_FNAME                ;  it's a "no param" error
  147. ;
  148. ;       SI now points to start of ASCIIZ string that we want to use as
  149. ;       the path/file name to search drives for
  150. ;
  151. ;       Put a byte of zeros at the end of string, and an "A:" in front
  152. ;       of string to initialize search.
  153. ;
  154. ADD_DRIVE:      MOV     BX,CX                   ;number of bytes remaining
  155.                 MOV     BYTE PTR [SI][BX],0     ;points to 1 char past end
  156.                                                 ; of string
  157.                 MOV     BYTE PTR [SI-2],'A'     ;"A:" in front of string
  158.                 MOV     BYTE PTR [SI-1],':'
  159. ;
  160. ;       Replace the current critical error handler with our own
  161. ;
  162. ;       First, get the address of the critical error handler assigned
  163. ;       by "parent" process (probably system) to this process.  Save its
  164. ;       address, so that we can use it if our handler is handed a non-disk
  165. ;       error  ( "we don't do non-disk errors ..." )
  166. ;
  167.                 MOV     AH,35H                  ;DOS fn "get vector"
  168.                 MOV     AL,24H                  ;"critical error" vector no.
  169.                 INT     21H                     ;call DOS
  170.                 MOV     WORD PTR PARENT_HAND,BX ;save offset vector adr
  171.                 MOV     WORD PTR PARENT_HAND+2,ES  ;save seg vector adr
  172. ;
  173. ;       Now, take control of critical error vector by assigning a handler
  174. ;       to the vector address.
  175. ;
  176. ;       DOS will restore the "parent"'s vector when this process returns to
  177. ;       DOS.
  178. ;
  179.                 MOV     DX,OFFSET CRIT_HAND     ;address of handler
  180.                 MOV     AL,24H                  ;the vector to be replaced
  181.                 MOV     AH,25H                  ;DOS fn call "ret int vector"
  182.                 INT     21H                     ;call DOS and replace vector
  183. ;
  184. ;       Get the number of drives that DOS knows about
  185. ;       Dont disturb the current default disk when getting the number
  186. ;
  187.                 MOV     AH,19H                  ;DOS fn "return current disk"
  188.                 INT     21H                     ;current disk returned in AL
  189.                 MOV     DL,AL                   ;put current in DL for sel call
  190.                 MOV     AH,0EH                  ;DOS fn "sel disk, return number
  191.                 INT     21H                     ;get number of drives
  192.                 SUB     CH,CH                   ;clear CH
  193.                 MOV     CL,AL                   ;number of drives
  194.                 INC     CX                      ;is now (1,2,3, or 4)
  195. ;
  196. ;       Now loop through all drives present, trying to find the file
  197. ;       (using fn call 4EH) on each drive.  If successful, return the
  198. ;       disk number to caller in errorlevel.
  199. ;
  200. ;       If not successful, return errorlevel = NOT_FOUND_CODE
  201. ;
  202.                 MOV     DX,SI                   ;offset adr of drive spec and
  203.                 DEC     DX                      ;  filename
  204.                 DEC     DX
  205. FIND_FILE:      MOV     AH,4EH                  ;DOS fn "find first file"
  206.                 PUSH    CX                      ;save the loop count
  207.                 SUB     CX,CX                   ;attribute says search
  208.                                                 ;"normal" files only
  209.                 PUSH    [SI-2]                  ;save drive letter (DOS call
  210.                                                 ;destroys it if file found)
  211.                 INT     21H                     ;call DOS
  212.                 POP     [SI-2]                  ;restore drive letter
  213.                 POP     CX                      ;restore loop count
  214.                 JNC     FOUND_FILE              ;if carry not set, then search
  215.                                                 ;was successful - jump.
  216.                 INC     BYTE PTR [SI-2]         ;increment drive letter char
  217.                 LOOP    FIND_FILE               ;and look on next drive
  218. ;
  219. ;       did not find file.  Return NOT_FOUND_CODE in errorlevel
  220. ;
  221. NO_FILE_EXIT:   MOV     AL,NOT_FOUND_CODE       ;file not found on any drive
  222. EXIT:           MOV     AH,4CH                  ;DOS fn call to exit w/ errlev
  223.                 INT     21H                     ;call DOS and exit
  224. ;
  225. ;       found the file.  Retrieve the drive letter used in this last call,
  226. ;       map it to disk number (A = 0, B = 1, etc) and return it in errorlevel.
  227. ;
  228. FOUND_FILE:     MOV     AL,[SI-2]               ;get the drive letter (upper
  229.                                                 ;case ascii code)
  230.                 SUB     AL,'A'                  ;map it to 0,1,2,3
  231.                 JMP     EXIT                    ;and return it in errorlevel
  232. START           ENDP
  233. page
  234. ;
  235. ;               CRIT_HAND               Critical Error Handler
  236. ;
  237. ;       This handler will be called by DOS functions when any critical
  238. ;       error (disk or non-disk) occurs during DOS INT 21H calls that
  239. ;       are made during execution of this process.
  240. ;
  241. ;       We only want to ignore disk errors, so we first test if the disk
  242. ;       is the cause of error.
  243. ;
  244. ;       If not a disk error, we jump to the parent's critical error handler
  245. ;       (we JMP so that stack looks as if we were never there).
  246. ;
  247. ;       If it is a disk error, we return an IGNORE code to the calling
  248. ;       DOS function.  The effect of all this is that when a DOS function
  249. ;       tries to access a disk drive that has a door open, or no disk, or
  250. ;       disk is unformatted, or disk is garbled, etc, the DOS function will
  251. ;       simply give up and return to the function's caller "empty handed".
  252. ;       There will be no "abort, retry, ignore" message from the critical
  253. ;       error handler.
  254. ;
  255. ;       on entry:       Bit 7 of AH = 0 if disk error
  256. ;                                   = 1 if not a disk error
  257. ;
  258. ;       on exit:        If disk error, we set AL = 0, "ignore error"
  259. ;
  260. ;       registers affected:     AH, AL
  261. ;
  262. CRIT_HAND       PROC    FAR                     ;RETS are typed FAR
  263.                 TEST    AH,80H                  ;bit 7 on?
  264.                 JNZ     NOT_DISK                ;jump if not disk error, we dont
  265.                                                 ;treat it
  266. ;
  267. ;       Treatment of disk errors is easy, just tell system to ignore them
  268. ;
  269.                 SUB     AL,AL                   ;zero AL, "ignore" code
  270.                 IRET                            ;caller used INT so we IRET
  271. ;
  272. ;       It was not a disk error, so let the "parent" critical error handler
  273. ;       treat it by JMPing to its address that we saved.
  274. ;
  275. ;       We JMP so we dont disturb the stack.  Stack looks like we were
  276. ;       never called.
  277. ;
  278. NOT_DISK:       JMP     DWORD PTR PARENT_HAND   ;jump to parent crit err hand
  279. ;
  280. CRIT_HAND       ENDP
  281. ;
  282. ;
  283. ;       temporary storage of parent's critical handler address
  284. ;
  285. PARENT_HAND     DD      1 DUP(?)                ;double word for FAR address
  286. ;
  287. ;
  288. ;
  289. ;       error message string
  290. ;
  291. ERROR_MESSAGE   DB      CR,LF,'***** No filename was given with '
  292.                 DB      'FINDFILE *****',CR,LF,'$'
  293. ;
  294. ;
  295. COM_CODE        ENDS
  296.                 END     START
  297.