2 ; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14
3 ; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14
4 TITLE PART4 COMMAND Transient routines
.
6 ; Internal commands DIR,PAUSE,ERASE,TYPE,VOL,VER
13 INCLUDE comequ
.asm
;AC000;
14 include ioctl
.inc ;AN000;
18 DATARES
SEGMENT PUBLIC BYTE ;AN020;
19 EXTRN append_flag
:byte ;AN020;
20 EXTRN append_state
:word ;AN020;
23 TRANDATA
SEGMENT PUBLIC BYTE ;AC000;
28 EXTRN dir_w_syn
:word ;AC000;
29 EXTRN dirdat_mo_day
:word ;AC000;
30 EXTRN dirdat_yr
:word ;AC000;
31 EXTRN dirdattim_ptr
:word
32 EXTRN dirhead_ptr
:word
33 EXTRN dirtim_hr_min
:word ;AC000;
35 EXTRN disp_file_size_ptr
:word
37 EXTRN Extend_buf_ptr
:word ;AN000;
38 EXTRN msg_disp_class
:byte ;AN000;
39 EXTRN parse_dir
:byte ;AC000;
40 EXTRN slash_p_syn
:word ;AC000;
41 EXTRN string_buf_ptr
:word
42 EXTRN tab_ptr
:word ;AC000;
45 TRANSPACE
SEGMENT PUBLIC BYTE ;AC000;
53 EXTRN dirflag
:byte ;AN015;
54 EXTRN display_ioctl
:word ;AC000;
55 EXTRN display_mode
:byte ;AC000;
57 EXTRN file_size_high
:word
58 EXTRN file_size_low
:word
61 EXTRN lincnt
:byte ;AC000;
63 EXTRN linperpag
:word ;AC000;
64 EXTRN msg_numb
:word ;AN022;
65 EXTRN parse1_addr
:dword ;AC000;
66 EXTRN parse1_syn
:word ;AC000;
67 EXTRN parse1_type
:byte ;AC000;
68 EXTRN pathcnt
:word ;AN000;
69 EXTRN pathpos
:word ;AN000;
70 EXTRN resseg
:word ;AN020;
71 EXTRN srcbuf
:byte ;AC000;
72 EXTRN string_ptr_2
:word
75 TRANCODE
SEGMENT PUBLIC BYTE
77 ASSUME
CS:TRANGROUP
,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
81 TRANSPACE
SEGMENT PUBLIC BYTE ;AC000;
82 EXTRN arg
:byte ; the arg structure!
93 break Catalog
- Directory command
94 assume
ds:trangroup
,es:trangroup
97 ; The DIR command displays the contents of a directory.
99 ; ****************************************************************
101 ; * ROUTINE: CATALOG - display file(s) in directory
103 ; * FUNCTION: PARSE command line for drive, file, or path name.
104 ; * DIR allows two switches, /P (pause) and /W (wide).
105 ; * If an error occurs issue and error message and
106 ; * transfer control to CERROR.
108 ; * INPUT: command line at offset 81H
112 ; ****************************************************************
117 ; Set up DTA for dir search firsts
119 mov dx,offset trangroup
:Dirbuf
;AC000; Set Disk transfer address
120 mov ah,Set_DMA
;AC000;
121 int int_command
;AC000;
123 ; Set up defaults for switches and parse the command line.
125 mov msg_numb
,0 ;AN022; initialize message flag
126 mov di,offset trangroup
:srcbuf
;AN000; get address of srcbuf
127 mov [pathpos
],di ;AN000; this is start of path
128 mov [pathcnt
],1 ;AN000; initialize length to 1 char
129 mov al,star
;AN000; initialize srcbuf to *,0d
131 mov al,end_of_line_in
;AN000;
133 mov si,81H
;AN000; Get command line
134 mov di,offset trangroup
:parse_dir
;AN000; Get adderss of PARSE_DIR
135 xor cx,cx ;AC000; clear counter for positionals
136 mov ComSw
,cx ;AC000; initialize flags
137 mov bits
,cx ;AC000; initialize switches
138 mov linperpag
,linesperpage
;AC000; Set default for lines per page
139 mov linlen
,normperlin
;AC000; Set number of entries per line
140 mov lincnt
,normperlin
;AC000;
144 invoke parse_with_msg
;AC018; call parser
145 cmp ax,end_of_line
;AN000; are we at end of line?
146 jne dirscan_cont
;AN000; No - continue parsing
147 jmp scandone
;AN000; yes - go process
150 cmp ax,result_no_error
;AN000; did we have an error?
151 jz dirscan_cont2
;AN000; No - continue parsing
152 jmp badparm
;AN000; yes - exit
155 cmp parse1_syn
,offset trangroup
:dir_w_syn
;AN000; was /W entered?
156 je set_dir_width
;AN000; yes - go set wide lines
157 cmp parse1_syn
,offset trangroup
:slash_p_syn
;AN000; was /P entered?
158 je set_dir_pause
;AN000; yes - go set pause at end of screen
160 ; Must be filespec since no other matches occurred. move filename to srcbuf
162 push si ;AC000; save position in line
163 lds si,parse1_addr
;AC000; get address of filespec
164 push si ;AN000; save address
165 invoke move_to_srcbuf
;AC000; move to srcbuf
166 pop dx ;AC000; get address in DX
169 ; The user may have specified a device. Search for the path and see if the
170 ; attributes indicate a device.
172 mov ah,Find_First
;AC000; find the file
173 int int_command
;AC000;
174 jnc Dir_check_device
;AN022; if no error - check device
175 invoke get_ext_error_number
;AN022; get the extended error
176 cmp ax,error_no_more_files
;AN022; was error no file found
177 jz Dir_fspec_end
;AC022; yes -> obviously not a device
178 cmp ax,error_path_not_found
;AN022; was error no file found
179 jz Dir_fspec_end
;AC022; yes -> obviously not a device
180 jmp dir_err_setup
;AN022; otherwise - go issue error message
182 dir_check_device: ;AN022;
183 test byte ptr (DirBuf
+find_buf_attr
),attr_device
;AC000;
184 jz Dir_fspec_end
;AC000; no, go do normal operation
185 mov ComSw
,-2 ;AC000; signal device
188 pop si ;AC000; restore position in line
189 jmp short dirscan
;AC000; keep parsing
192 test byte ptr[bits
],SwitchW
;AN018; /W already set?
193 jz ok_set_width
;AN018; no - okay to set width
194 mov ax,moreargs_ptr
;AN018; set up too many arguments
195 invoke setup_parse_error_msg
;AN018; set up an error message
196 jmp badparm
;AN018; exit
199 or bits
,switchw
;AC000; indicate /w was selected
200 mov linlen
,wideperlin
;AC000; Set number of entries per line
201 mov lincnt
,wideperlin
;AC000;
202 jmp short dirscan
;AC000; keep parsing
205 test byte ptr[bits
],SwitchP
;AN018; /p already set?
206 jz ok_set_pause
;AN018; no - okay to set width
207 mov ax,moreargs_ptr
;AN018; set up too many arguments
208 invoke setup_parse_error_msg
;AN018; set up an error message
209 jmp badparm
;AN018; exit
212 or bits
,switchp
;AC000; indicate /p was selected
213 push cx ;AN000; save necessary registers
215 mov ax,(IOCTL
SHL 8) + generic_ioctl_handle
;AN000; get lines per page on display
216 mov bx,stdout
;AN000; lines for stdout
217 mov ch,ioc_sc
;AN000; type is display
218 mov cl,get_generic
;AN000; get information
219 mov dx,offset trangroup
:display_ioctl
;AN000;
220 int int_command
;AN000;
223 dec linperpag
;AN000; lines per actual page should
224 dec linperpag
;AN000; two less than the max
225 mov ax,linperpag
;AN000; get number of lines into
226 mov [fullscr
],ax ;AC000; screen line counter
227 pop si ;AN000; restore registers
229 jmp dirscan
;AC000; keep parsing
232 ; The syntax is incorrect. Report only message we can.
235 jmp cerror
;AC000; invalid switches get displayed
240 ; Find and display the volume ID on the drive.
243 invoke okvolarg
;AC000;
244 mov [filecnt
],0 ;AC000; Keep track of how many files found
245 cmp comsw
,0 ;AC000; did an error occur?
246 jnz doheader
;AC000; yes - don't bother to fix path
248 mov dirflag
,-1 ;AN015; set pathcrunch called from DIR
249 invoke pathcrunch
;AC000; set up FCB for dir
250 mov dirflag
,0 ;AN015; reset dirflag
251 jc DirCheckPath
;AC015; no CHDIRs worked.
252 jz doheader
;AC015; chdirs worked - path\*.*
253 mov si,[desttail
] ;AN015; get filename back
254 jmp short DoRealParse
;AN015; go parse it
257 mov ax,[msg_numb
] ;AN022; get message number
258 cmp ax,0 ;AN022; Is there a message?
259 jnz dir_err_setup
;AN022; yes - there's an error
260 cmp [destisdir
],0 ;AC000; Were pathchars found?
261 jz doparse
;AC000; no - no problem
262 inc comsw
;AC000; indicate error
263 jmp short doheader
;AC000; go print header
266 mov ax,error_file_not_found
;AN022; get message number in control block
269 mov msg_disp_class
,ext_msg_class
;AN000; set up extended error msg class
270 mov dx,offset TranGroup
:Extend_Buf_ptr
;AC000; get extended message pointer
271 mov extend_buf_ptr
,ax ;AN022;
277 ; We have changed to something. We also have a file. Parse it into a
278 ; reasonable form, leaving drive alone, leaving extention alone and leaving
279 ; filename alone. We need to special case ... If we are at the root, the
280 ; parse will fail and it will give us a file not found instead of file not
284 mov si,offset trangroup
:srcbuf
;AN000; Get address of source
285 cmp byte ptr [si+1],colon_char
;AN000; Is there a drive?
286 jnz dir_no_drive
;AN000; no - keep going
287 lodsw ;AN000; bypass drive
292 cmp byte ptr [si+2],0
298 mov di,FCB
; where to put the file name
299 mov ax,(Parse_File_Descriptor
SHL 8) OR 0EH
303 ; Check to see if APPEND installed. If it is installed, set all flags
304 ; off. This will be reset in the HEADFIX routine
308 mov ax,AppendInstall
;AN020; see if append installed
310 cmp al,0 ;AN020; append installed?
311 je DoHeaderCont
;AN020; no - continue
312 mov ax,AppendDOS
;AN020; see if append DOS version right
314 cmp ax,-1 ;AN020; append version correct?
315 jne DoHeaderCont
;AN020; no - continue
316 mov ax,AppendGetState
;AN020; Get the state of Append
318 push ds ;AN020; save current data segment
319 mov ds,[resseg
] ;AN020; get resident segment
320 assume
ds:resgroup
;AN020;
321 mov append_state
,bx ;AN020; save append state
322 mov append_flag
,-1 ;AN020; set append flag
323 xor bx,bx ;AN020; clear out state
324 mov ax,AppendSetState
;AN020; Set the state of Append
325 int 2fh
;AN020; set everything off
326 pop ds ;AN020; save current data segment
327 assume
ds:trangroup
;AN020;
334 mov al,blank
;AN051; Print out a blank
335 invoke print_char
;AN051; before DIR header
336 invoke build_dir_string
; get current dir string
337 mov dx,offset trangroup
:Dirhead_ptr
338 invoke printf_crlf
; bang!
341 ; If there were chars left after parse or device, then invalid file name
344 jz DoSearch
; nothing left; good parse
345 jl DirNFFix
; not .. => error file not found
347 mov dx,offset TranGroup
:BadCD_ptr
348 jmp Cerror
; was .. => error directory not found
353 ; We are assured that everything is correct. Let's go and search. Use
354 ; attributes that will include finding directories. perform the first search
355 ; and reset our directory afterward.
358 mov byte ptr DS:[FCB
-7],0FFH
359 mov byte ptr DS:[FCB
-1],010H
361 ; Caution! Since we are using an extended FCB, we will *also* be returning
362 ; the directory information as an extended FCB. We must bias all fetches into
363 ; DIRBUF by 8 (Extended FCB part + drive)
365 mov ah,Dir_Search_First
369 push ax ;AN022; save return state
370 inc al ;AN022; did an error occur?
371 pop ax ;AN022; get return state back
372 jnz found_first_file
;AN022; no error - start dir
373 invoke set_ext_error_msg
;AN022; yes - set up error message
374 push dx ;AN022; save message
375 invoke restudir
;AN022; restore user's dir
376 pop dx ;AN022; restore message
377 cmp word ptr Extend_Buf_Ptr
,Error_No_More_Files
;AN022; convert no more files to
378 jnz DirCerrorJ
;AN022; file not found
379 mov Extend_Buf_Ptr
,Error_File_Not_Found
;AN022;
382 jmp Cerror
;AN022; exit
385 ; Restore the user's directory. We preserve, though, the return from the
386 ; previous system call for later checking.
394 ; Main scanning loop. Entry has AL = Search first/next error code. Test for
398 inc al ; FF = file not found
400 jmp DirDone
; Either an error or we are finished
402 ; Note that we've seen a file and display the found file.
406 inc [filecnt
] ; Keep track of how many we find
407 mov si,offset trangroup
:dirbuf
+8 ; SI -> information returned by sys call
410 ; If we are displaying in wide mode, do not output the file info
412 test byte ptr[bits
],SwitchW
; W switch set?
414 jmp nexent
; If so, no size, date, or time
417 ; Test for directory.
420 test [dirbuf
+8].dir_attr
,attr_directory
423 ; We have a directory. Display the <DIR> field in place of the file size
425 mov dx,offset trangroup
:Dmes_ptr
429 ; We have a file. Display the file size
432 mov dx,[DirBuf
+8].dir_size_l
434 mov dx,[DirBuf
+8].dir_size_h
435 mov file_size_high
,dx
436 mov dx,offset trangroup
:disp_file_size_ptr
439 ; Display time and date of last modification
442 mov ax,[DirBuf
+8].dir_date
; Get date
444 ; If the date is 0, then we have found a 1.x level diskette. We skip the
445 ; date/time fields as 1.x did not have them.
448 jz nexent
; Skip if no date
454 shr ax,cl ; Align month
455 and al,0FH ; Get month
458 shr cl,1 ; Align year
460 add cx,80 ; Relative 1980
466 xchg dh,dl ;AN000; switch month & day
467 mov DirDat_yr
,cx ;AC000; put year into message control block
468 mov DirDat_mo_day
,dx ;AC000; put month and day into message control block
469 mov cx,[DirBuf
+8].dir_time
; Get time
470 jcxz prbuf
; Time field present?
475 shr cl,1 ; Hours in CH, minutes in CL
476 xchg ch,cl ;AN000; switch hours & minutes
477 mov DirTim_hr_min
,cx ;AC000; put hours and minutes into message subst block
480 mov dx,offset trangroup
:DirDatTim_ptr
482 invoke crlf2
;AC066;end the line
483 dec byte ptr [fullscr
] ;AC066;count the line
484 jnz endif04
;AN066;IF the last on the screen THEN
485 call check_for_P
;AN066; pause if /P requested
487 jmp scroll
; If not, just continue
488 ;AD061; mov DirDat_yr,0 ;AC000; reset year, month and day
489 ;AD061; mov DirDat_mo_day,0 ;AC000; in control block
490 ;AD061; mov DirTim_hr_min,0 ;AC000; reset hour & minute in control block
492 ; We are done displaying an entry. The code between "noexent:" and "scroll:"
493 ; is only for /W case.
496 mov bl,[lincnt
] ;AN066;save for check for first entry on line
497 dec [lincnt
] ;count this entry on the line
498 jnz else01
;AX066;IF last entry on line THEN
502 cmp [fullscr
],0 ;AC066;IF have filled the screen THEN
504 call check_for_P
;AN066; reinitialize fullscr,
505 endif02: ;AN066; IF P requested THEN pause
506 jmp short endif01
;AN066;
507 else01: ;AN066;ELSE since screen not full
508 cmp bl,[linlen
] ;AN066; IF starting new line THEN
509 jne endif03
; count the line
510 dec byte ptr [fullscr
] ;AN066; ENDIF
511 endif03: ;AC066;We are outputting on the same line, between fields, we tab.
512 mov dx,offset trangroup
:tab_ptr
;Output a tab
516 ; All we need to do now is to get the next directory entry.
519 mov ah,Dir_Search_Next
520 mov dx,FCB
-7 ; DX -> Unopened FCB
521 int int_command
; Search for a file to match FCB
524 ; If no files have been found, display a not-found message
527 invoke get_ext_error_number
;AN022; get the extended error number
528 cmp ax,error_no_more_files
;AN022; was error file not found?
529 jnz dir_err_setup_jmp
;AN022; no - setup error message
532 mov ax,error_file_not_found
;AN022;
534 dir_err_setup_jmp: ;AN022;
535 jmp dir_err_setup
;AN022; go setup error msg & print it
537 ; If we have printed the maximum number of files per line, terminate it with
542 cmp al,[lincnt
] ; Will be equal if just had CR/LF
545 cmp [fullscr
],0 ;AN066;IF on last line of screen THEN
546 jnz endif06
;AN066; pause before going on
547 call check_for_P
;AN066; to number and freespace
548 endif06: ;AN066; displays
551 mov dx,offset trangroup
:Dirmes_ptr
555 mov ah,Get_Drive_Freespace
556 mov dl,byte ptr DS:[FCB
]
560 mul cx ; AX is bytes per cluster
562 mov bytes_free
,ax ;AC000;
563 mov bytes_free
+2,dx ;AC000;
564 MOV DX,OFFSET TRANGROUP
:BYTMES_ptr
568 mov di,offset trangroup
:charbuf
578 mov dx,offset trangroup
:charbuf
580 mov dx,offset trangroup
:string_buf_ptr
585 check_for_P PROC
NEAR ;AN066;
587 test byte ptr[bits
],SwitchP
;P switch present?
589 mov ax,linperpag
;AN000; transfer lines per page
590 mov [fullscr
],ax ;AC000; to fullscr
595 check_for_P ENDP
;AN066;