summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/COMMAND/TCMD1A.ASM
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/CMD/COMMAND/TCMD1A.ASM
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/CMD/COMMAND/TCMD1A.ASM')
-rw-r--r--v4.0/src/CMD/COMMAND/TCMD1A.ASM598
1 files changed, 598 insertions, 0 deletions
diff --git a/v4.0/src/CMD/COMMAND/TCMD1A.ASM b/v4.0/src/CMD/COMMAND/TCMD1A.ASM
new file mode 100644
index 0000000..fd662b3
--- /dev/null
+++ b/v4.0/src/CMD/COMMAND/TCMD1A.ASM
@@ -0,0 +1,598 @@
1 page 80,132
2; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14
3; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14
4TITLE 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
18DATARES SEGMENT PUBLIC BYTE ;AN020;
19 EXTRN append_flag:byte ;AN020;
20 EXTRN append_state:word ;AN020;
21DATARES ENDS ;AN020;
22
23TRANDATA 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;
43TRANDATA ENDS
44
45TRANSPACE 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
73TRANSPACE ENDS
74
75TRANCODE SEGMENT PUBLIC BYTE
76
77ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
78
79;---------------
80
81TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
82 EXTRN arg:byte ; the arg structure!
83TRANSPACE ENDS
84;---------------
85
86 EXTRN cerror:near
87 EXTRN std_printf:near
88
89
90 PUBLIC catalog
91
92
93 break Catalog - Directory command
94assume 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
114CATALOG:
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
142dirscan:
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
149dirscan_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
154dirscan_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
182dir_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
187dir_fspec_end:
188 pop si ;AC000; restore position in line
189 jmp short dirscan ;AC000; keep parsing
190
191set_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
198ok_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
204set_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
211ok_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
222lines_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;
234BadParm:
235 jmp cerror ;AC000; invalid switches get displayed
236
237ScanDone:
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
256DirCheckPath:
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
265DirNF:
266 mov ax,error_file_not_found ;AN022; get message number in control block
267
268dir_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
273DirError:
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;
283DoParse:
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
289dir_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
297DoRealParse:
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
307DoHeader:
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
333DoHeaderCont:
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
349DirNFFix:
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;
357DoSearch:
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
381DirCerrorJ: ;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
389found_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;
397DIRSTART:
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
405Display:
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;
419DirTest:
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;
431fileent:
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;
441nofsiz:
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
465millenium:
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
479prbuf:
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;
495nexent:
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;
518scroll:
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;
526DirDone:
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
534dir_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;
540Trailer:
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
550mmessage:
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
567shoname:
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
585check_for_P PROC NEAR ;AN066;
586
587test byte ptr[bits],SwitchP ;P switch present?
588jz endif05 ;AN066;
589 mov ax,linperpag ;AN000; transfer lines per page
590 mov [fullscr],ax ;AC000; to fullscr
591 invoke Pause
592endif05:
593ret ;AN066;
594
595check_for_P ENDP ;AN066;
596
597trancode ends
598 end