|
|
page ,132 ; SCCSID = @(#)tenv2.asm 1.1 85/05/14 ; SCCSID = @(#)tenv2.asm 1.1 85/05/14 TITLE Part6 COMMAND Transient routines. ;/* ; * Microsoft Confidential ; * Copyright (C) Microsoft Corporation 1991 ; * All Rights Reserved. ; */
; Environment utilities and misc. routines
.xlist .xcref include comsw.asm include dossym.inc include syscall.inc include find.inc include comseg.asm include comequ.asm .list .cref
DATARES SEGMENT PUBLIC BYTE ;AC000; EXTRN pipeflag:byte DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000; EXTRN ACRLF_PTR:WORD EXTRN BadCD_Ptr:WORD EXTRN Badmkd_ptr:word EXTRN BADRMD_PTR:WORD EXTRN Extend_buf_ptr:word ;AN000; EXTRN Extend_buf_sub:byte ;AN022; EXTRN MD_exists_ptr:word ;AN006; EXTRN msg_disp_class:byte ;AC000; EXTRN NOSPACE_PTR:WORD EXTRN parse_chdir:byte ;AC000; EXTRN parse_mrdir:byte ;AC000; EXTRN PIPEEMES_PTR:WORD EXTRN string_buf_ptr:word TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000; EXTRN CURDRV:BYTE EXTRN DESTINFO:BYTE EXTRN DESTTAIL:WORD EXTRN DIRCHAR:BYTE EXTRN dirflag:byte ;AN015; EXTRN KPARSE:BYTE ;AC000; 3/3/KK EXTRN msg_numb:word ;AN022; EXTRN parse1_addr:dword ;AC000; EXTRN parse1_type:byte ;AC000; EXTRN PATHPOS:WORD EXTRN RESSEG:WORD EXTRN srcxname:byte ;AC000; EXTRN string_ptr_2:word EXTRN SWITCHAR:BYTE EXTRN USERDIR1:BYTE TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC byte
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN cerror:near
PUBLIC $chdir PUBLIC $mkdir PUBLIC $rmdir PUBLIC crlf2 PUBLIC crprint PUBLIC delim PUBLIC error_output PUBLIC fcb_to_ascz PUBLIC pathchrcmp PUBLIC pathcrunch PUBLIC savudir PUBLIC savudir1 PUBLIC scanoff PUBLIC strcomp
break $Chdir
; **************************************************************** ; * ; * ROUTINE: $CHDIR ; * ; * FUNCTION: Entry point for CHDIR command. Parse the command ; * line. If path is found, CHDIR to path. If a drive ; * letter is found, get and display the current dir ; * of the specified drive. If nothing is found, get ; * and display the current dir of the default drive. ; * ; * INPUT: command line at offset 81H ; * ; * OUTPUT: none ; * ; ****************************************************************
assume ds:trangroup,es:trangroup
$CHDIR:
mov si,81H mov di,offset trangroup:parse_chdir ;AN000; Get adderss of PARSE_CHDIR xor cx,cx ;AN000; clear cx,dx xor dx,dx ;AN000; invoke parse_with_msg ;AC018; call parser
cmp ax,end_of_line ;AC000; are we at end of line? jz bwdJ ; No args cmp ax,result_no_error ;AC000; did we have an error? jnz ChDirErr ;AC018; yes - exit
cmp parse1_type,result_drive ;AC000; was a drive entered? jnz REALCD ; no ; ; D: was found. See if there is anything more. ; mov di,offset trangroup:parse_chdir ;AC000; get address of parse_chdir xor dx,dx ;AC000; invoke parse_check_eol ;AC000; call parser jnz ChDirErr ;AC000;
bwdJ: invoke build_dir_for_chdir ; Drive only specified call crlf2 return
REALCD:
push si ;AN000; save position in line lds si,parse1_addr ;AN000; get address of filespec invoke move_to_srcbuf ;AN000; move to srcbuf pop si ;AN000; restore position in line mov di,offset trangroup:parse_chdir ;AC000; get address of parse_chdir xor dx,dx ;AC000; invoke parse_check_eol ;AC000; call parser jnz ChDirErr ;AC000;
invoke SETPATH TEST [DESTINFO],2 JNZ BadChdir MOV AH,CHDIR INT 21h retnc
invoke get_ext_error_number ;AN022; get the extended error cmp ax,error_path_not_found ;AN022; see if path not found jz BadChDir ;AN022; yes - issue old message ;SR; ; We want to issue "Invalid Directory" message even if the path is valid ;but is not a directory. The extended error returns "Access denied" which ;is kind of confusing. Issue the old message if access denied error is ;returned ; cmp ax,error_access_denied jz BadChDir
call Set_Ext_Error_Subst ;AN022; jmp short chdirerr ;AN022;
BadChDir: MOV DX,OFFSET TRANGROUP:BADCD_ptr
ChDirErr: invoke Std_Eprintf return
break $Mkdir
assume ds:trangroup,es:trangroup
$MKDIR: CALL SETRMMK JC MkDirErr MOV AH,MKDIR INT 21h retnc
invoke get_ext_error_number ;AN022; get the extended error cmp ax,error_path_not_found ;AN022; see if path not found jz MD_other_err ;AN022; yes - issue old message cmp ax,error_access_denied ;AN022; access denied? jz badmderr ;AN022; yes - see if file exists
call Set_Ext_Error_Subst ;AN022; jmp short MkDirerr ;AC022; yes - go print it
BADMDERR: mov dx,offset trangroup:srcxname ;AN006; Set Disk transfer address mov ah,Set_DMA ;AN006; int 21h ;AN006; MOV AH,Find_First ;AN006; see if file/dir exists mov cx,attr_directory ;AN006; search for directory INT 21h ;AN006; jc MD_other_err ;AN006; doesn't exist - must be something else mov dl,srcxname.find_buf_attr ;AN006; we found a file/dir test dl,attr_directory ;AN006; was it a directory? jz MD_other_err ;AN006; no - must have been a file mov dx,offset trangroup:MD_exists_ptr ;AN006; set up already exists error jmp short MkDirErr ;AN006; make sure we didn't have network error MD_other_err: ;AN006; MOV DX,OFFSET TRANGROUP:BADMKD_ptr MkDirErr: invoke Std_Eprintf return
Break <Common MkDir/RmDir set up code>
;**************************************************************** ;* ;* ROUTINE: SETRMMK ;* ;* FUNCTION: Parse routine for the internal MKDIR and RMDIR ;* commands. Parses the command line for a required ;* filespec. ;* ;* INPUT: command line at offset 81H ;* ;* OUTPUT: carry clear ;* DS:DX points to ASCIIZ argument ;* carry set ;* DS:DX has error message pointer ;* ;****************************************************************
SETRMMK: mov si,81H mov di,offset trangroup:parse_mrdir ;AN000; Get adderss of PARSE_MRDIR xor cx,cx ;AN000; clear cx,dx xor dx,dx ;AN000; invoke parse_with_msg ;AC000; call parser cmp ax,result_no_error ;AC000; did we have an error? jnz NOARGERR ;AC000; yes - exit
mov di,offset trangroup:srcxname ;AN000; get address of srcxname push di ;AN000; save address push si ;AN000; save position in line lds si,parse1_addr ;AN000; get address of path
mrdir_move_filename: ;AN000; put filespec in srcxname lodsb ;get a char from buffer stosb ;AN000; store in srcxname cmp al,end_of_line_out ;AC000; it char a terminator? jnz mrdir_move_filename ;AC000; no - keep moving pop si ;AN000; get line position back
; ; we have scanned an argument. See if any args beyond. ;
mov di,offset trangroup:parse_mrdir ;AC000; get address of parse_mrdir invoke parse_check_eol ;AC000; are we at end of line? pop dx ;AC000; get address of SRCXNAME retz ;yes - return no error NOARGERR: mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer XOR AX,AX STC return
break $Rmdir
assume ds:trangroup,es:trangroup
$RMDIR: CALL SETRMMK JC RmDirErr JNZ BADRDERR MOV AH,RMDIR INT 21h retnc
invoke get_ext_error_number ;AN022; get the extended error cmp ax,error_path_not_found ;AN022; see if path not found jz badrderr ;AN022; yes - issue old message cmp ax,error_access_denied ;AN022; access denied? jz badrderr ;AN022; yes - issue old message
call Set_Ext_Error_Subst ;AN022; jmp short RmDirerr ;AC022; yes - go print it
BADRDERR: MOV DX,OFFSET TRANGROUP:BADRMD_ptr
RmDirErr: invoke STD_Eprintf return
;**************************************************************** ;* ;* ROUTINE: Set_ext_error_subst ;* ;* FUNCTION: Sets up substitution for extended error ;* ;* INPUT: AX - extended error number ;* DX - offset of string ;* ;* OUTPUT: Extend_Buf_Ptr set up for STD_EPRINTF ;* ;****************************************************************
Set_ext_error_subst proc near ;AN022;
mov msg_disp_class,ext_msg_class ;AN022; set up extended error msg class mov string_ptr_2,dx ;AN022; get address of failed string mov Extend_buf_sub,one_subst ;AN022; put number of subst in control block mov dx,offset TranGroup:Extend_Buf_ptr ;AN022; get extended message pointer mov Extend_Buf_ptr,ax ;AN022; get message number in control block
ret ;AN022; return
Set_ext_error_subst endp ;AN022;
Break <SavUDir - preserve the users current directory on a particular drive>
; ; SavUDir - move the user's current directory on a drive into UserDir1 ; SavUDir1 - move the user's current directory on a drive into a specified ; buffer ; ; Inputs: DL has 1-based drive number ; ES:DI has destination buffer (SavUDir1 only) ; Outputs: Carry Clear ; DS = TranGroup ; Carry Set ; AX has error code ; Registers Modified: AX, SI ;
SAVUDIR: MOV DI,OFFSET TRANGROUP:USERDIR1
SAVUDIR1: MOV AL,DL ADD AL,'@' CMP AL,'@' JNZ GOTUDRV ADD AL,[CURDRV] INC AL ; A = 1
GOTUDRV: STOSB MOV AH,[DIRCHAR] MOV AL,':' STOSW PUSH ES POP DS ASSUME DS:NOTHING
MOV SI,DI MOV AH,CURRENT_DIR ; Get the Directory Text INT 21h retc PUSH CS POP DS ASSUME DS:TRANGROUP
return
CRLF2: PUSH DX MOV DX,OFFSET TRANGROUP:ACRLF_ptr
PR: PUSH DS PUSH CS POP DS invoke std_printf POP DS POP DX
return
; ; These routines (SCANOFF, DELIM) are called in batch processing when DS ; may NOT be TRANGROUP ; ASSUME DS:NOTHING,ES:NOTHING
SCANOFF: LODSB CALL DELIM JZ SCANOFF DEC SI ; Point to first non-delimiter return
; ; Input: AL is character to classify ; Output: Z set if delimiter ; NZ set otherwise ; Registers modified: none ;
DELIM: CMP AL,' ' retz CMP AL,'=' retz CMP AL,',' retz CMP AL,';' retz CMP AL,9 ; Check for TAB character retz CMP AL,0ah ; Check for line feed character - BAS return
ASSUME DS:TRANGROUP,ES:TRANGROUP
FCB_TO_ASCZ: ; Convert DS:SI to ASCIZ ES:DI MOV CX,8
MAINNAME: LODSB CMP AL,' ' JZ SKIPSPC STOSB
SKIPSPC: LOOP MAINNAME LODSB CMP AL,' ' JZ GOTNAME MOV AH,AL MOV AL,dot_chr STOSB XCHG AL,AH STOSB MOV CL,2
EXTNAME: LODSB CMP AL,' ' JZ GOTNAME STOSB LOOP EXTNAME
GOTNAME: XOR AL,AL STOSB return
STRCOMP: ; ; Compare ASCIZ DS:SI with ES:DI. ; SI,DI destroyed. ; CMPSB retnz ; Strings not equal cmp byte ptr [SI-1],0 ; Hit NUL terminator? retz ; Yes, strings equal jmp short STRCOMP ; Equal so far, keep going
CRPRINT: PUSH AX MOV AL,13 PUSH CX PUSH DI MOV DI,DX MOV CX,-1 PUSH ES PUSH DS POP ES
REPNZ SCASB ; LOOK FOR TERMINATOR mov byte ptr [di-1],0 ; nul terminate the string POP ES mov string_ptr_2,dx mov dx,offset trangroup:string_buf_ptr invoke std_printf mov ds:byte ptr [di-1],13 ; now put the CR back JC ERROR_OUTPUT
POP DI POP CX POP AX
return
ERROR_OUTPUT: PUSH CS POP DS ASSUME DS:TRANGROUP MOV ES,[RESSEG] ASSUME ES:RESGROUP
MOV DX,OFFSET TRANGROUP:NOSPACE_ptr CMP [PIPEFLAG],0 JZ GO_TO_ERROR
invoke PipeOff MOV DX,OFFSET TRANGROUP:PIPEEMES_ptr GO_TO_ERROR: JMP CERROR
ASSUME DS:TRANGROUP,ES:TRANGROUP
PATHCHRCMP: ;---- Mod for path invocation ---- PUBLIC pathchrcmp ;----
push ax mov ah,'/' CMP [SWITCHAR],ah JZ NOSLASHT CMP AL,'/' jz pccont
NOSLASHT: CMP AL,'\' pccont: pop ax
return
; ; PATHCRUNCH - ; ; ENTRY FCB (in PSP) contains drive # to crunch on ; PathPos = ptr to string with pathname in it ; PathCnt = length of string ; ; EXIT PathPos = ptr after pathname (w/ NULL) in string ; PathCnt = length left in string ; DestIsDir = nonzero if pathname delimiter char's found in pathname ; DestInfo<bit1> = set if wildcard char's found in pathname ; If path crunched successfully, ; CY = clear ; Current directory is changed to directory in pathname ; UserDir1 contains previous directory for use by RestUDir ; RestDir = nonzero to flag later restoration of user's dir ; DestTail = ptr to beginning of filename ; If filename found in pathname, ; ZR = clear ; FCB filename fields contain filename ; If filename not found (pure directory path), ; ZR = set ; FCB filename fields are wildcarded with ?'s ; If pathcrunch failed (no ChDir's worked), ; CY = set ; Msg_Numb = extended error code ; ; NOTE DIR asks PathCrunch to forego parsing the filename into the ; FCB by setting DirFlag. In this case, the FCB is returned ; with the filename wildcarded. ; PATHCRUNCH: mov [msg_numb],0 ;AN022; Set up message flag MOV DL,DS:[FCB] ; DL = drive # (1 = A) CALL SAVUDIR ; save current directory in UserDir1 jc pcrunch_cderrJ ;AN022; if error on current dir - report
invoke SETPATH ; scan past switches, whitespace
; DX = ptr to pathname, NULL-terminated ; PathPos = ptr to byte after NULL at end of pathname
TEST [DESTINFO],2 ; test if wildcards (? or *) seen JNZ TRYPEEL ; wildcard seen, peel filename
MOV AH,CHDIR ; AH = DOS ChDir function code INT 21h ; call DOS jnc chdir_worked ;AN022; no error - continue
invoke get_ext_error_number ;AN022; get the extended error cmp ax,error_path_not_found ;AN022; if path not found jz trypeel ;AC022; keep trying cmp ax,error_access_denied ;AN022; if access denied jz trypeel ;AC022; keep trying mov [msg_numb],ax ;AN022; set up message flag jmp peelfail ;AN022; exit with other error
chdir_worked: invoke SETREST1 ; set 'Restore Directory' flag true MOV AL,'?' ; if pure dir, wildcard filename in FCB MOV DI,5DH MOV CX,11 REP STOSB XOR AL,AL ; return carry clear, zero set return
pcrunch_cderrj: ;AN022; need this for long jmp jmp pcrunch_cderr ;AN022;
TRYPEEL: MOV SI,[PATHPOS] DEC SI ; SI = ptr to NULL at end of pathname MOV AL,[SI-1] ; AL = last char of pathname
CMP [KPARSE],0 JNZ DELSTRT ; Last char is second KANJI byte, might be '\'
CALL PATHCHRCMP JZ PEELFAIL ; Trailing '/'
DELSTRT: MOV CX,SI ; CX = ptr to NULL at end of pathname MOV SI,DX ; SI = ptr to start of pathname PUSH DX ; save ptr to pathname DELLOOP: CMP SI,CX JZ GOTDELE ; no char's left, we have what we have LODSB ; AL = next char of pathname invoke TESTKANJ JZ NOTKANJ8 ; not Kanji, move along INC SI JMP DELLOOP
NOTKANJ8: CALL PATHCHRCMP JNZ DELLOOP ; not a path delimiter, keep looking MOV DX,SI DEC DX ; DX = ptr to last delimiter found JMP DELLOOP ; go look for more
GOTDELE: MOV SI,DX ; SI = ptr to pathname or last delim POP DX ; DX = ptr to pathname CMP SI,DX JZ BADRET ; didn't find path delim MOV CX,SI ; CX = ptr to last path delimiter MOV SI,DX ; SI = ptr to pathname
DELLOOP2: ; Set value of KPARSE CMP SI,CX JZ TRYCD ; roll up till SI meets CX MOV [KPARSE],0 LODSB INVOKE TESTKANJ JZ DELLOOP2 INC SI INC [KPARSE] JMP DELLOOP2
TRYCD: push ax mov al,dot_chr ; AL = '.' CMP BYTE PTR [SI+1],al ; check for '.' after path delim ;M019; allow continuation if '. ' or ;M019; '..' is not found. jnz @F ;M019; '.' not found cmp BYTE PTR [SI+2],al ;M019; check for '..' jz @F ;M019; found '..' cmp BYTE PTR [SI+2],0 ;M019; check for '. ' (null terminated) @@: pop ax JZ PEELFAIL ; if . or .., pure cd should have worked mov al,[si-1] CMP al,':' ; Special case d:\file JZ BADRET
CMP [KPARSE],0 JNZ NOTDOUBLESL ; Last char is second KANJI byte, might be '\'
CALL PATHCHRCMP JNZ NOTDOUBLESL PEELFAIL: STC ; // return NOTDOUBLESL: MOV BYTE PTR [SI],0 MOV AH,CHDIR INT 21h JNC CDSUCC pcrunch_cderr: invoke get_ext_error_number ;AN022; get the extended error mov [msg_numb],ax ;AN022; set up message flag or si,si ;AN022; set up zero flag to not zero stc ;AN022; set up carry flag return
BADRET: MOV AL,[SI] CALL PATHCHRCMP ; Special case 'DIRCHAR'file STC retnz XOR BL,BL XCHG BL,[SI+1] MOV AH,CHDIR INT 21h jc pcrunch_cderr ;AN022; go to error exit MOV [SI+1],BL CDSUCC: invoke SETREST1 INC SI ; Reset zero MOV [DESTTAIL],SI pushf ;AN015; save flags cmp dirflag,-1 ;AN015; don't do parse if in DIR jz pcrunch_end ;AN015; MOV DI,FCB MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 02H ; Parse with default drive INT 21h pcrunch_end: popf ;AN015; get flags back return
trancode ends end
|