]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/CMD/COMMAND/TCMD1A.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / CMD / COMMAND / TCMD1A.ASM
1 page 80,132
2 ; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14
3 ; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14
4 TITLE PART4 COMMAND Transient routines.
5
6 ; Internal commands DIR,PAUSE,ERASE,TYPE,VOL,VER
7
8 INCLUDE comsw.asm
9 .xlist
10 .xcref
11 INCLUDE DOSSYM.INC
12 INCLUDE comseg.asm
13 INCLUDE comequ.asm ;AC000;
14 include ioctl.inc ;AN000;
15 .list
16 .cref
17
18 DATARES SEGMENT PUBLIC BYTE ;AN020;
19 EXTRN append_flag:byte ;AN020;
20 EXTRN append_state:word ;AN020;
21 DATARES ENDS ;AN020;
22
23 TRANDATA SEGMENT PUBLIC BYTE ;AC000;
24 EXTRN BadCD_ptr:word
25 EXTRN bits:word
26 EXTRN Bytmes_ptr:word
27 EXTRN comsw:word
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;
34 EXTRN Dirmes_ptr:word
35 EXTRN disp_file_size_ptr:word
36 EXTRN Dmes_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;
43 TRANDATA ENDS
44
45 TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
46 EXTRN bytes_free:word
47 EXTRN charbuf:byte
48 EXTRN COM:byte
49 EXTRN Destisdir:byte
50 EXTRN Desttail:word
51 EXTRN dir_num:word
52 EXTRN Dirbuf:byte
53 EXTRN dirflag:byte ;AN015;
54 EXTRN display_ioctl:word ;AC000;
55 EXTRN display_mode:byte ;AC000;
56 EXTRN filecnt:word
57 EXTRN file_size_high:word
58 EXTRN file_size_low:word
59 EXTRN fullscr:word
60 EXTRN ID:byte
61 EXTRN lincnt:byte ;AC000;
62 EXTRN linlen:byte
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
73 TRANSPACE ENDS
74
75 TRANCODE SEGMENT PUBLIC BYTE
76
77 ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
78
79 ;---------------
80
81 TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
82 EXTRN arg:byte ; the arg structure!
83 TRANSPACE ENDS
84 ;---------------
85
86 EXTRN cerror:near
87 EXTRN std_printf:near
88
89
90 PUBLIC catalog
91
92
93 break Catalog - Directory command
94 assume ds:trangroup,es:trangroup
95
96 ;
97 ; The DIR command displays the contents of a directory.
98 ;
99 ; ****************************************************************
100 ; *
101 ; * ROUTINE: CATALOG - display file(s) in directory
102 ; *
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.
107 ; *
108 ; * INPUT: command line at offset 81H
109 ; *
110 ; * OUTPUT: none
111 ; *
112 ; ****************************************************************
113
114 CATALOG:
115
116 ;
117 ; Set up DTA for dir search firsts
118 ;
119 mov dx,offset trangroup:Dirbuf ;AC000; Set Disk transfer address
120 mov ah,Set_DMA ;AC000;
121 int int_command ;AC000;
122 ;
123 ; Set up defaults for switches and parse the command line.
124 ;
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
130 stosb ;AN000;
131 mov al,end_of_line_in ;AN000;
132 stosb ;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;
141
142 dirscan:
143 xor dx,dx ;AN000;
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
148
149 dirscan_cont:
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
153
154 dirscan_cont2:
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
159 ;
160 ; Must be filespec since no other matches occurred. move filename to srcbuf
161 ;
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
167
168 ;
169 ; The user may have specified a device. Search for the path and see if the
170 ; attributes indicate a device.
171 ;
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
181
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
186
187 dir_fspec_end:
188 pop si ;AC000; restore position in line
189 jmp short dirscan ;AC000; keep parsing
190
191 set_dir_width:
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
197
198 ok_set_width:
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
203
204 set_dir_pause:
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
210
211 ok_set_pause:
212 or bits,switchp ;AC000; indicate /p was selected
213 push cx ;AN000; save necessary registers
214 push si ;AN000;
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;
221
222 lines_set:
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
228 pop cx ;AN000;
229 jmp dirscan ;AC000; keep parsing
230
231 ;
232 ; The syntax is incorrect. Report only message we can.
233 ;
234 BadParm:
235 jmp cerror ;AC000; invalid switches get displayed
236
237 ScanDone:
238
239 ;
240 ; Find and display the volume ID on the drive.
241 ;
242
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
247
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
255
256 DirCheckPath:
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
264
265 DirNF:
266 mov ax,error_file_not_found ;AN022; get message number in control block
267
268 dir_err_setup:
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;
272
273 DirError:
274 jmp Cerror
275
276 ;
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
281 ; found.
282 ;
283 DoParse:
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
288
289 dir_no_drive:
290 cmp [si],".."
291 jnz DoRealParse
292 cmp byte ptr [si+2],0
293 jnz DoRealParse
294 inc ComSw
295 jmp short DoHeader
296
297 DoRealParse:
298 mov di,FCB ; where to put the file name
299 mov ax,(Parse_File_Descriptor SHL 8) OR 0EH
300 int int_command
301
302 ;
303 ; Check to see if APPEND installed. If it is installed, set all flags
304 ; off. This will be reset in the HEADFIX routine
305 ;
306
307 DoHeader:
308 mov ax,AppendInstall ;AN020; see if append installed
309 int 2fh ;AN020;
310 cmp al,0 ;AN020; append installed?
311 je DoHeaderCont ;AN020; no - continue
312 mov ax,AppendDOS ;AN020; see if append DOS version right
313 int 2fh ;AN020;
314 cmp ax,-1 ;AN020; append version correct?
315 jne DoHeaderCont ;AN020; no - continue
316 mov ax,AppendGetState ;AN020; Get the state of Append
317 int 2fh ;AN020;
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;
328
329 ;
330 ; Display the header
331 ;
332
333 DoHeaderCont:
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!
339
340 ;
341 ; If there were chars left after parse or device, then invalid file name
342 ;
343 cmp ComSw,0
344 jz DoSearch ; nothing left; good parse
345 jl DirNFFix ; not .. => error file not found
346 invoke RestUDir
347 mov dx,offset TranGroup:BadCD_ptr
348 jmp Cerror ; was .. => error directory not found
349 DirNFFix:
350 invoke RestUDir
351 jmp DirNF
352 ;
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.
356 ;
357 DoSearch:
358 mov byte ptr DS:[FCB-7],0FFH
359 mov byte ptr DS:[FCB-1],010H
360 ;
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)
364 ;
365 mov ah,Dir_Search_First
366 mov dx,FCB-7
367 int int_command
368
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;
380
381 DirCerrorJ: ;AN022;
382 jmp Cerror ;AN022; exit
383
384 ;
385 ; Restore the user's directory. We preserve, though, the return from the
386 ; previous system call for later checking.
387 ;
388
389 found_first_file:
390 push ax
391 invoke restudir
392 pop ax
393 ;
394 ; Main scanning loop. Entry has AL = Search first/next error code. Test for
395 ; no more.
396 ;
397 DIRSTART:
398 inc al ; FF = file not found
399 jnz Display
400 jmp DirDone ; Either an error or we are finished
401 ;
402 ; Note that we've seen a file and display the found file.
403 ;
404
405 Display:
406 inc [filecnt] ; Keep track of how many we find
407 mov si,offset trangroup:dirbuf+8 ; SI -> information returned by sys call
408 call shoname
409 ;
410 ; If we are displaying in wide mode, do not output the file info
411 ;
412 test byte ptr[bits],SwitchW ; W switch set?
413 jz DirTest
414 jmp nexent ; If so, no size, date, or time
415
416 ;
417 ; Test for directory.
418 ;
419 DirTest:
420 test [dirbuf+8].dir_attr,attr_directory
421 jz fileent
422 ;
423 ; We have a directory. Display the <DIR> field in place of the file size
424 ;
425 mov dx,offset trangroup:Dmes_ptr
426 call std_printf
427 jmp short nofsiz
428 ;
429 ; We have a file. Display the file size
430 ;
431 fileent:
432 mov dx,[DirBuf+8].dir_size_l
433 mov file_size_low,dx
434 mov dx,[DirBuf+8].dir_size_h
435 mov file_size_high,dx
436 mov dx,offset trangroup:disp_file_size_ptr
437 call std_printf
438 ;
439 ; Display time and date of last modification
440 ;
441 nofsiz:
442 mov ax,[DirBuf+8].dir_date ; Get date
443 ;
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.
446 ;
447 or ax,ax
448 jz nexent ; Skip if no date
449 mov bx,ax
450 and ax,1FH ; get day
451 mov dl,al
452 mov ax,bx
453 mov cl,5
454 shr ax,cl ; Align month
455 and al,0FH ; Get month
456 mov dh,al
457 mov cl,bh
458 shr cl,1 ; Align year
459 xor ch,ch
460 add cx,80 ; Relative 1980
461 cmp cl,100
462 jb millenium
463 sub cl,100
464
465 millenium:
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?
471 shr cx,1
472 shr cx,1
473 shr cx,1
474 shr cl,1
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
478
479 prbuf:
480 mov dx,offset trangroup:DirDatTim_ptr
481 call std_printf
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
486 endif04: ;AN066;
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
491 ;
492 ; We are done displaying an entry. The code between "noexent:" and "scroll:"
493 ; is only for /W case.
494 ;
495 nexent:
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
499 mov al,[linlen]
500 mov [lincnt],al
501 invoke crlf2
502 cmp [fullscr],0 ;AC066;IF have filled the screen THEN
503 jnz endif02 ;AN066;
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
513 call std_printf
514 endif01: ;AX066;
515 ;
516 ; All we need to do now is to get the next directory entry.
517 ;
518 scroll:
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
522 jmp DirStart
523 ;
524 ; If no files have been found, display a not-found message
525 ;
526 DirDone:
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
530 test [filecnt],-1
531 jnz Trailer
532 mov ax,error_file_not_found ;AN022;
533
534 dir_err_setup_jmp: ;AN022;
535 jmp dir_err_setup ;AN022; go setup error msg & print it
536 ;
537 ; If we have printed the maximum number of files per line, terminate it with
538 ; CRLF.
539 ;
540 Trailer:
541 mov al,[linlen]
542 cmp al,[lincnt] ; Will be equal if just had CR/LF
543 jz mmessage
544 invoke crlf2
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
549
550 mmessage:
551 mov dx,offset trangroup:Dirmes_ptr
552 mov si,[filecnt]
553 mov dir_num,si
554 call std_printf
555 mov ah,Get_Drive_Freespace
556 mov dl,byte ptr DS:[FCB]
557 int int_command
558 cmp ax,-1
559 retz
560 mul cx ; AX is bytes per cluster
561 mul bx
562 mov bytes_free,ax ;AC000;
563 mov bytes_free+2,dx ;AC000;
564 MOV DX,OFFSET TRANGROUP:BYTMES_ptr
565 jmp std_printf
566
567 shoname:
568 mov di,offset trangroup:charbuf
569 mov cx,8
570 rep movsb
571 mov al,' '
572 stosb
573 mov cx,3
574 rep movsb
575 xor ax,ax
576 stosb
577 push dx
578 mov dx,offset trangroup:charbuf
579 mov string_ptr_2,dx
580 mov dx,offset trangroup:string_buf_ptr
581 call std_printf
582 pop DX
583 return
584
585 check_for_P PROC NEAR ;AN066;
586
587 test byte ptr[bits],SwitchP ;P switch present?
588 jz endif05 ;AN066;
589 mov ax,linperpag ;AN000; transfer lines per page
590 mov [fullscr],ax ;AC000; to fullscr
591 invoke Pause
592 endif05:
593 ret ;AN066;
594
595 check_for_P ENDP ;AN066;
596
597 trancode ends
598 end