From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/CMD/COMMAND/TCMD1A.ASM | 598 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 598 insertions(+) create mode 100644 v4.0/src/CMD/COMMAND/TCMD1A.ASM (limited to 'v4.0/src/CMD/COMMAND/TCMD1A.ASM') 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 @@ + 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 + +DATARES SEGMENT PUBLIC BYTE ;AN020; + EXTRN append_flag:byte ;AN020; + EXTRN append_state:word ;AN020; +DATARES ENDS ;AN020; + +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 resseg:word ;AN020; + 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; + 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: + mov ax,AppendInstall ;AN020; see if append installed + int 2fh ;AN020; + cmp al,0 ;AN020; append installed? + je DoHeaderCont ;AN020; no - continue + mov ax,AppendDOS ;AN020; see if append DOS version right + int 2fh ;AN020; + cmp ax,-1 ;AN020; append version correct? + jne DoHeaderCont ;AN020; no - continue + mov ax,AppendGetState ;AN020; Get the state of Append + int 2fh ;AN020; + push ds ;AN020; save current data segment + mov ds,[resseg] ;AN020; get resident segment + assume ds:resgroup ;AN020; + mov append_state,bx ;AN020; save append state + mov append_flag,-1 ;AN020; set append flag + xor bx,bx ;AN020; clear out state + mov ax,AppendSetState ;AN020; Set the state of Append + int 2fh ;AN020; set everything off + pop ds ;AN020; save current data segment + assume ds:trangroup ;AN020; + +; +; 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