2025-04-27 07:49:33 -04:00

596 lines
17 KiB
NASM
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
************************************************************
************************************************************
** **
** THIS FILE IS OBSOLETE, NO LONGER USED, DEFUNCT, **
** AND, IN FACT, DOESN'T EVEN EXIST. YOU ARE NOT **
** HERE. YOU MAY NOT BE ANYWHERE AT ALL. THIS **
** WHOLE THING COULDN'T POSSIBLY BE HAPPENING. **
** **
** See DIR.ASM for a reality check. **
** **
************************************************************
************************************************************
page 80,132
; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14
; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14
TITLE PART4 COMMAND Transient routines.
; Internal commands DIR,PAUSE,ERASE,TYPE,VOL,VER
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm ;AC000;
include ioctl.inc ;AN000;
.list
.cref
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BadCD_ptr:word
EXTRN bits:word
EXTRN Bytmes_ptr:word
EXTRN comsw:word
EXTRN dir_w_syn:word ;AC000;
EXTRN dirdat_mo_day:word ;AC000;
EXTRN dirdat_yr:word ;AC000;
EXTRN dirdattim_ptr:word
EXTRN dirhead_ptr:word
EXTRN dirtim_hr_min:word ;AC000;
EXTRN Dirmes_ptr:word
EXTRN disp_file_size_ptr:word
EXTRN Dmes_ptr:word
EXTRN Extend_buf_ptr:word ;AN000;
EXTRN msg_disp_class:byte ;AN000;
EXTRN parse_dir:byte ;AC000;
EXTRN slash_p_syn:word ;AC000;
EXTRN string_buf_ptr:word
EXTRN tab_ptr:word ;AC000;
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN bytes_free:word
EXTRN charbuf:byte
EXTRN COM:byte
EXTRN Destisdir:byte
EXTRN Desttail:word
EXTRN dir_num:word
EXTRN Dirbuf:byte
EXTRN dirflag:byte ;AN015;
EXTRN display_ioctl:word ;AC000;
EXTRN display_mode:byte ;AC000;
EXTRN filecnt:word
EXTRN file_size_high:word
EXTRN file_size_low:word
EXTRN fullscr:word
EXTRN ID:byte
EXTRN lincnt:byte ;AC000;
EXTRN linlen:byte
EXTRN linperpag:word ;AC000;
EXTRN msg_numb:word ;AN022;
EXTRN parse1_addr:dword ;AC000;
EXTRN parse1_syn:word ;AC000;
EXTRN parse1_type:byte ;AC000;
EXTRN pathcnt:word ;AN000;
EXTRN pathpos:word ;AN000;
EXTRN srcbuf:byte ;AC000;
EXTRN string_ptr_2:word
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte ; the arg structure!
TRANSPACE ENDS
;---------------
EXTRN cerror:near
EXTRN std_printf:near
PUBLIC catalog
break Catalog - Directory command
assume ds:trangroup,es:trangroup
;
; The DIR command displays the contents of a directory.
;
; ****************************************************************
; *
; * ROUTINE: CATALOG - display file(s) in directory
; *
; * FUNCTION: PARSE command line for drive, file, or path name.
; * DIR allows two switches, /P (pause) and /W (wide).
; * If an error occurs issue and error message and
; * transfer control to CERROR.
; *
; * INPUT: command line at offset 81H
; *
; * OUTPUT: none
; *
; ****************************************************************
CATALOG:
;
; Set up DTA for dir search firsts
;
mov dx,offset trangroup:Dirbuf ;AC000; Set Disk transfer address
mov ah,Set_DMA ;AC000;
int int_command ;AC000;
;
; Set up defaults for switches and parse the command line.
;
mov msg_numb,0 ;AN022; initialize message flag
mov di,offset trangroup:srcbuf ;AN000; get address of srcbuf
mov [pathpos],di ;AN000; this is start of path
mov [pathcnt],1 ;AN000; initialize length to 1 char
mov al,star ;AN000; initialize srcbuf to *,0d
stosb ;AN000;
mov al,end_of_line_in ;AN000;
stosb ;AN000;
mov si,81H ;AN000; Get command line
mov di,offset trangroup:parse_dir ;AN000; Get adderss of PARSE_DIR
xor cx,cx ;AC000; clear counter for positionals
mov ComSw,cx ;AC000; initialize flags
mov bits,cx ;AC000; initialize switches
mov linperpag,linesperpage ;AC000; Set default for lines per page
mov linlen,normperlin ;AC000; Set number of entries per line
mov lincnt,normperlin ;AC000;
dirscan:
xor dx,dx ;AN000;
invoke parse_with_msg ;AC018; call parser
cmp ax,end_of_line ;AN000; are we at end of line?
jne dirscan_cont ;AN000; No - continue parsing
jmp scandone ;AN000; yes - go process
dirscan_cont:
cmp ax,result_no_error ;AN000; did we have an error?
jz dirscan_cont2 ;AN000; No - continue parsing
jmp badparm ;AN000; yes - exit
dirscan_cont2:
cmp parse1_syn,offset trangroup:dir_w_syn ;AN000; was /W entered?
je set_dir_width ;AN000; yes - go set wide lines
cmp parse1_syn,offset trangroup:slash_p_syn ;AN000; was /P entered?
je set_dir_pause ;AN000; yes - go set pause at end of screen
;
; Must be filespec since no other matches occurred. move filename to srcbuf
;
push si ;AC000; save position in line
lds si,parse1_addr ;AC000; get address of filespec
push si ;AN000; save address
invoke move_to_srcbuf ;AC000; move to srcbuf
pop dx ;AC000; get address in DX
;
; The user may have specified a device. Search for the path and see if the
; attributes indicate a device.
;
mov ah,Find_First ;AC000; find the file
int int_command ;AC000;
jnc Dir_check_device ;AN022; if no error - check device
invoke get_ext_error_number ;AN022; get the extended error
cmp ax,error_no_more_files ;AN022; was error no file found
jz Dir_fspec_end ;AC022; yes -> obviously not a device
cmp ax,error_path_not_found ;AN022; was error no file found
jz Dir_fspec_end ;AC022; yes -> obviously not a device
jmp dir_err_setup ;AN022; otherwise - go issue error message
dir_check_device: ;AN022;
test byte ptr (DirBuf+find_buf_attr),attr_device ;AC000;
jz Dir_fspec_end ;AC000; no, go do normal operation
mov ComSw,-2 ;AC000; signal device
dir_fspec_end:
pop si ;AC000; restore position in line
jmp short dirscan ;AC000; keep parsing
set_dir_width:
test byte ptr[bits],SwitchW ;AN018; /W already set?
jz ok_set_width ;AN018; no - okay to set width
mov ax,moreargs_ptr ;AN018; set up too many arguments
invoke setup_parse_error_msg ;AN018; set up an error message
jmp badparm ;AN018; exit
ok_set_width:
or bits,switchw ;AC000; indicate /w was selected
mov linlen,wideperlin ;AC000; Set number of entries per line
mov lincnt,wideperlin ;AC000;
jmp short dirscan ;AC000; keep parsing
set_dir_pause:
test byte ptr[bits],SwitchP ;AN018; /p already set?
jz ok_set_pause ;AN018; no - okay to set width
mov ax,moreargs_ptr ;AN018; set up too many arguments
invoke setup_parse_error_msg ;AN018; set up an error message
jmp badparm ;AN018; exit
ok_set_pause:
or bits,switchp ;AC000; indicate /p was selected
push cx ;AN000; save necessary registers
push si ;AN000;
mov ax,(IOCTL SHL 8) + generic_ioctl_handle ;AN000; get lines per page on display
mov bx,stdout ;AN000; lines for stdout
mov ch,ioc_sc ;AN000; type is display
mov cl,get_generic ;AN000; get information
mov dx,offset trangroup:display_ioctl ;AN000;
int int_command ;AN000;
lines_set:
dec linperpag ;AN000; lines per actual page should
dec linperpag ;AN000; two less than the max
mov ax,linperpag ;AN000; get number of lines into
mov [fullscr],ax ;AC000; screen line counter
pop si ;AN000; restore registers
pop cx ;AN000;
jmp dirscan ;AC000; keep parsing
;
; The syntax is incorrect. Report only message we can.
;
BadParm:
jmp cerror ;AC000; invalid switches get displayed
ScanDone:
;
; Find and display the volume ID on the drive.
;
invoke okvolarg ;AC000;
;
; OkVolArg also disables APPEND, which will be re-enabled
; in the HeadFix routine, after we're done.
;
mov [filecnt],0 ;AC000; Keep track of how many files found
cmp comsw,0 ;AC000; did an error occur?
jnz doheader ;AC000; yes - don't bother to fix path
mov dirflag,-1 ;AN015; set pathcrunch called from DIR
invoke pathcrunch ;AC000; set up FCB for dir
mov dirflag,0 ;AN015; reset dirflag
jc DirCheckPath ;AC015; no CHDIRs worked.
jz doheader ;AC015; chdirs worked - path\*.*
mov si,[desttail] ;AN015; get filename back
jmp short DoRealParse ;AN015; go parse it
DirCheckPath:
mov ax,[msg_numb] ;AN022; get message number
cmp ax,0 ;AN022; Is there a message?
jnz dir_err_setup ;AN022; yes - there's an error
cmp [destisdir],0 ;AC000; Were pathchars found?
jz doparse ;AC000; no - no problem
inc comsw ;AC000; indicate error
jmp short doheader ;AC000; go print header
DirNF:
mov ax,error_file_not_found ;AN022; get message number in control block
dir_err_setup:
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov extend_buf_ptr,ax ;AN022;
DirError:
jmp Cerror
;
; We have changed to something. We also have a file. Parse it into a
; reasonable form, leaving drive alone, leaving extention alone and leaving
; filename alone. We need to special case ... If we are at the root, the
; parse will fail and it will give us a file not found instead of file not
; found.
;
DoParse:
mov si,offset trangroup:srcbuf ;AN000; Get address of source
cmp byte ptr [si+1],colon_char ;AN000; Is there a drive?
jnz dir_no_drive ;AN000; no - keep going
lodsw ;AN000; bypass drive
dir_no_drive:
cmp [si],".."
jnz DoRealParse
cmp byte ptr [si+2],0
jnz DoRealParse
inc ComSw
jmp short DoHeader
DoRealParse:
mov di,FCB ; where to put the file name
mov ax,(Parse_File_Descriptor SHL 8) OR 0EH
int int_command
;
; Check to see if APPEND installed. If it is installed, set all flags
; off. This will be reset in the HEADFIX routine
;
DoHeader:
; ORIGINAL APPEND CHECK CODE LOCATION ******************************
;
; Display the header
;
DoHeaderCont:
mov al,blank ;AN051; Print out a blank
invoke print_char ;AN051; before DIR header
invoke build_dir_string ; get current dir string
mov dx,offset trangroup:Dirhead_ptr
invoke printf_crlf ; bang!
;
; If there were chars left after parse or device, then invalid file name
;
cmp ComSw,0
jz DoSearch ; nothing left; good parse
jl DirNFFix ; not .. => error file not found
invoke RestUDir
mov dx,offset TranGroup:BadCD_ptr
jmp Cerror ; was .. => error directory not found
DirNFFix:
invoke RestUDir
jmp DirNF
;
; We are assured that everything is correct. Let's go and search. Use
; attributes that will include finding directories. perform the first search
; and reset our directory afterward.
;
DoSearch:
mov byte ptr DS:[FCB-7],0FFH
mov byte ptr DS:[FCB-1],010H
;
; Caution! Since we are using an extended FCB, we will *also* be returning
; the directory information as an extended FCB. We must bias all fetches into
; DIRBUF by 8 (Extended FCB part + drive)
;
mov ah,Dir_Search_First
mov dx,FCB-7
int int_command
push ax ;AN022; save return state
inc al ;AN022; did an error occur?
pop ax ;AN022; get return state back
jnz found_first_file ;AN022; no error - start dir
invoke set_ext_error_msg ;AN022; yes - set up error message
push dx ;AN022; save message
invoke restudir ;AN022; restore user's dir
pop dx ;AN022; restore message
cmp word ptr Extend_Buf_Ptr,Error_No_More_Files ;AN022; convert no more files to
jnz DirCerrorJ ;AN022; file not found
mov Extend_Buf_Ptr,Error_File_Not_Found ;AN022;
DirCerrorJ: ;AN022;
jmp Cerror ;AN022; exit
;
; Restore the user's directory. We preserve, though, the return from the
; previous system call for later checking.
;
found_first_file:
push ax
invoke restudir
pop ax
;
; Main scanning loop. Entry has AL = Search first/next error code. Test for
; no more.
;
DIRSTART:
inc al ; FF = file not found
jnz Display
jmp DirDone ; Either an error or we are finished
;
; Note that we've seen a file and display the found file.
;
Display:
inc [filecnt] ; Keep track of how many we find
mov si,offset trangroup:dirbuf+8 ; SI -> information returned by sys call
call shoname
;
; If we are displaying in wide mode, do not output the file info
;
test byte ptr[bits],SwitchW ; W switch set?
jz DirTest
jmp nexent ; If so, no size, date, or time
;
; Test for directory.
;
DirTest:
test [dirbuf+8].dir_attr,attr_directory
jz fileent
;
; We have a directory. Display the <DIR> field in place of the file size
;
mov dx,offset trangroup:Dmes_ptr
call std_printf
jmp short nofsiz
;
; We have a file. Display the file size
;
fileent:
mov dx,[DirBuf+8].dir_size_l
mov file_size_low,dx
mov dx,[DirBuf+8].dir_size_h
mov file_size_high,dx
mov dx,offset trangroup:disp_file_size_ptr
call std_printf
;
; Display time and date of last modification
;
nofsiz:
mov ax,[DirBuf+8].dir_date ; Get date
;
; If the date is 0, then we have found a 1.x level diskette. We skip the
; date/time fields as 1.x did not have them.
;
or ax,ax
jz nexent ; Skip if no date
mov bx,ax
and ax,1FH ; get day
mov dl,al
mov ax,bx
mov cl,5
shr ax,cl ; Align month
and al,0FH ; Get month
mov dh,al
mov cl,bh
shr cl,1 ; Align year
xor ch,ch
add cx,80 ; Relative 1980
cmp cl,100
jb millenium
sub cl,100
millenium:
xchg dh,dl ;AN000; switch month & day
mov DirDat_yr,cx ;AC000; put year into message control block
mov DirDat_mo_day,dx ;AC000; put month and day into message control block
mov cx,[DirBuf+8].dir_time ; Get time
jcxz prbuf ; Time field present?
shr cx,1
shr cx,1
shr cx,1
shr cl,1
shr cl,1 ; Hours in CH, minutes in CL
xchg ch,cl ;AN000; switch hours & minutes
mov DirTim_hr_min,cx ;AC000; put hours and minutes into message subst block
prbuf:
mov dx,offset trangroup:DirDatTim_ptr
call std_printf
invoke crlf2 ;AC066;end the line
dec byte ptr [fullscr] ;AC066;count the line
jnz endif04 ;AN066;IF the last on the screen THEN
call check_for_P ;AN066; pause if /P requested
endif04: ;AN066;
jmp scroll ; If not, just continue
;AD061; mov DirDat_yr,0 ;AC000; reset year, month and day
;AD061; mov DirDat_mo_day,0 ;AC000; in control block
;AD061; mov DirTim_hr_min,0 ;AC000; reset hour & minute in control block
;
; We are done displaying an entry. The code between "noexent:" and "scroll:"
; is only for /W case.
;
nexent:
mov bl,[lincnt] ;AN066;save for check for first entry on line
dec [lincnt] ;count this entry on the line
jnz else01 ;AX066;IF last entry on line THEN
mov al,[linlen]
mov [lincnt],al
invoke crlf2
cmp [fullscr],0 ;AC066;IF have filled the screen THEN
jnz endif02 ;AN066;
call check_for_P ;AN066; reinitialize fullscr,
endif02: ;AN066; IF P requested THEN pause
jmp short endif01 ;AN066;
else01: ;AN066;ELSE since screen not full
cmp bl,[linlen] ;AN066; IF starting new line THEN
jne endif03 ; count the line
dec byte ptr [fullscr] ;AN066; ENDIF
endif03: ;AC066;We are outputting on the same line, between fields, we tab.
mov dx,offset trangroup:tab_ptr ;Output a tab
call std_printf
endif01: ;AX066;
;
; All we need to do now is to get the next directory entry.
;
scroll:
mov ah,Dir_Search_Next
mov dx,FCB-7 ; DX -> Unopened FCB
int int_command ; Search for a file to match FCB
jmp DirStart
;
; If no files have been found, display a not-found message
;
DirDone:
invoke get_ext_error_number ;AN022; get the extended error number
cmp ax,error_no_more_files ;AN022; was error file not found?
jnz dir_err_setup_jmp ;AN022; no - setup error message
test [filecnt],-1
jnz Trailer
mov ax,error_file_not_found ;AN022;
dir_err_setup_jmp: ;AN022;
jmp dir_err_setup ;AN022; go setup error msg & print it
;
; If we have printed the maximum number of files per line, terminate it with
; CRLF.
;
Trailer:
mov al,[linlen]
cmp al,[lincnt] ; Will be equal if just had CR/LF
jz mmessage
invoke crlf2
cmp [fullscr],0 ;AN066;IF on last line of screen THEN
jnz endif06 ;AN066; pause before going on
call check_for_P ;AN066; to number and freespace
endif06: ;AN066; displays
mmessage:
mov dx,offset trangroup:Dirmes_ptr
mov si,[filecnt]
mov dir_num,si
call std_printf
mov ah,Get_Drive_Freespace
mov dl,byte ptr DS:[FCB]
int int_command
cmp ax,-1
retz
mul cx ; AX is bytes per cluster
mul bx
mov bytes_free,ax ;AC000;
mov bytes_free+2,dx ;AC000;
MOV DX,OFFSET TRANGROUP:BYTMES_ptr
jmp std_printf
shoname:
mov di,offset trangroup:charbuf
mov cx,8
rep movsb
mov al,' '
stosb
mov cx,3
rep movsb
xor ax,ax
stosb
push dx
mov dx,offset trangroup:charbuf
mov string_ptr_2,dx
mov dx,offset trangroup:string_buf_ptr
call std_printf
pop DX
return
check_for_P PROC NEAR ;AN066;
test byte ptr[bits],SwitchP ;P switch present?
jz endif05 ;AN066;
mov ax,linperpag ;AN000; transfer lines per page
mov [fullscr],ax ;AC000; to fullscr
invoke Pause
endif05:
ret ;AN066;
check_for_P ENDP ;AN066;
trancode ends
end