Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

923 lines
22 KiB

page ,132
; SCCSID = @(#)tmisc1.asm 4.1 85/09/22
; SCCSID = @(#)tmisc1.asm 4.1 85/09/22
TITLE Part7 COMMAND Transient Routines
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
;
; Revision History
; ================
; M003 SR 07/16/90 Made Execute public to jump to it for
; LoadHigh support
;
; M025 SR 9/12/90 Removed calls to SetStdInOn,SetStdInOff
; SetStdOutOn & SetStdOutOff.
;
; More misc routines
.xlist
.xcref
include comsw.asm
include dossym.inc
include syscall.inc
include comseg.asm
include comequ.asm
.list
.cref
CODERES SEGMENT PUBLIC BYTE ;AC000;
;; EXTRN RSTACK:BYTE
CodeRes ENDS
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN CALL_FLAG:BYTE
EXTRN EchoFlag:BYTE
EXTRN EXEC_BLOCK:BYTE
EXTRN EXTCOM:BYTE
EXTRN LenMsgOrPathBuf:ABS
EXTRN PIPEFLAG:BYTE
EXTRN PIPEPTR:WORD
EXTRN PIPESTR:BYTE
EXTRN RESTDIR:BYTE
EXTRN RE_OUT_APP:BYTE
EXTRN RE_OUTSTR:BYTE
EXTRN SAFEPATHBUFFER:BYTE
extrn RStack:word
ifdef BETA3WARN
%out Take this out before we ship
EXTRN Beta3Warned:byte
EXTRN TrnSeg:word
endif
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BADDRV_PTR:WORD
EXTRN BADNAM_PTR:WORD
EXTRN COMTAB:BYTE ;AC000;
EXTRN extend_buf_ptr:word ;AN000;
EXTRN msg_disp_class:byte ;AN000;
ifdef BETA3WARN
%out Take this out before we ship
EXTRN Beta3WarnMsg:byte
endif
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte ; the arg structure!
EXTRN ALLSWITCH:WORD
EXTRN APPEND_EXEC:BYTE ;AN041;
EXTRN CHKDRV:BYTE
EXTRN COMBUF:BYTE
EXTRN COMSW:WORD
EXTRN EXECPATH:BYTE
EXTRN EXEC_ADDR:DWORD
EXTRN FILTYP:BYTE
EXTRN IDLEN:BYTE
EXTRN KPARSE:BYTE ;AC000;
EXTRN PARM1:BYTE
EXTRN PARM2:BYTE
EXTRN PathPos:word
EXTRN RESSEG:WORD
EXTRN RE_INSTR:BYTE
EXTRN SPECDRV:BYTE
EXTRN SWITCHAR:BYTE
EXTRN switch_list:byte
EXTRN TRAN_TPA:WORD
EXTRN EXECPATH_SIZE:WORD
EXTRN EXECEXT_TYPE:WORD
IF IBM
EXTRN ROM_CALL:BYTE
EXTRN ROM_CS:WORD
EXTRN ROM_IP:WORD
ENDIF
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC byte
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN APPEND_PARSE:NEAR ;AN010;
EXTRN BATCOM:NEAR
EXTRN DOCOM1:NEAR
EXTRN PIPEERRSYN:NEAR
EXTRN TCOMMAND:NEAR
IF IBM
EXTRN ROM_EXEC:NEAR
EXTRN ROM_SCAN:NEAR
ENDIF
PUBLIC CERROR
PUBLIC DRVBAD
PUBLIC EXTERNAL
PUBLIC FNDCOM
PUBLIC PRESCAN
PUBLIC SWITCH
public Lh_Execute ; M051
ASSUME DS:TRANGROUP
;---------------------------
; We can get rid of this switch processing code if we can take
; care of the remaining two calls to switch, later in the file.
; However, I have not checked whether or not any other files use
; switch -- after all, it IS public!
;---------------------------
SWCOUNT EQU 6 ; Length of switch_list
RETSW:
XCHG AX,BX ; Put switches in AX
return
SWITCH:
XOR BX,BX ; Initialize - no switches set
SWLOOP:
INVOKE SCANOFF ; Skip any delimiters
CMP AL,[SWITCHAR] ; Is it a switch specifier?
JNZ RETSW ; No -- we're finished
OR BX,fSwitch ; Indicate there is a switch specified
INC SI ; Skip over the switch character
INVOKE SCANOFF
CMP AL,0DH
JZ RETSW ; Oops
INC SI
; Convert lower case input to upper case
INVOKE UPCONV
MOV DI,OFFSET TRANGROUP:switch_list
MOV CX,SWCOUNT
REPNE SCASB ; Look for matching switch
JNZ BADSW
MOV AX,1
SHL AX,CL ; Set a bit for the switch
OR BX,AX
JMP SHORT SWLOOP
BADSW:
JMP SHORT SWLOOP
DRVBAD:
MOV DX,OFFSET TRANGROUP:BADDRV_ptr
JMP CERROR
externalj:
jmp EXTERNAL
fndcom: ; search the internal command table
OR AL,AL ; Get real length of first arg
jz externalj ; If 0, it must begin with "\" so has
; to be external.
; barryf code starts here
ifndef NEC_98
IF IBM
call test_append ; see if APPEND installed
je contcom ; not loaded
append_internal:
mov cl,TRANGROUP:IDLEN
mov ch,0
mov pathpos,cx
inc append_exec ;AN041; set APPEND to ON
invoke ioset ; re-direct the o'l io
mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set
mov DX,-1 ; set invoke function
mov di,offset TRANGROUP:APPEND_PARSE;AN010; Get the entry point for PARSE for APPEND
mov AX,0AE01H
int 2FH ; execute command
cmp TRANGROUP:IDLEN,0 ; execute requested
;; je Cmd_done
jne contcom
jmp Cmd_done
contcom: ; continue with internal scan
ENDIF
else ;NEC_98
call test_append ; see if APPEND installed
je contcom ; not loaded
append_internal:
mov cl,TRANGROUP:IDLEN
mov ch,0
mov pathpos,cx
inc append_exec ;AN041; set APPEND to ON
invoke ioset ; re-direct the o'l io
mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set
mov DX,-1 ; set invoke function
mov di,offset TRANGROUP:APPEND_PARSE;AN010; Get the entry point for PARSE for APPEND
mov AX,0AE01H
int 2FH ; execute command
cmp TRANGROUP:IDLEN,0 ; execute requested
;; je Cmd_done
jne contcom
jmp Cmd_done
contcom: ; continue with internal scan
endif ;NEC_98
; barryf code ends here
mov DI, OFFSET TRANGROUP:COMTAB
XOR CX,CX
findcom:
mov SI, offset TRANGROUP:IDLEN+1 ; pointer to command argument
mov CL, [DI] ; load length of internal command
inc di ; advance past length
jcxz externalj ; if it's zero, we're out of internals
cmp CL, IDLEN ; that of the command argument
jnz abcd ; lengths not equal ==> strings not eq
MOV PathPos,CX ; store length of command
repz cmpsb
abcd:
lahf ; save the good ol' flags
add DI, CX ; skip over remaining internal, if any
mov AL, BYTE PTR [DI] ; load drive-check indicator byte (DCIB)
mov [CHKDRV], AL ; save command flag byte in chkdrv
inc DI ; increment DI (OK, OK, I'll stop)
mov BX, WORD PTR [DI] ; load internal command address
inc DI ; skip over the puppy
inc DI
mov DX, WORD PTR [DI] ; load ptr to help msg #s
inc DI
inc DI
sahf ; remember those flags?
jnz findcom ; well, if all the cmps worked...
;
; All messages get redirected.
;
cmp append_exec,0 ;AN041; APPEND just executed?
jnz dont_set_io ;AN041; Yes - this junk is already set
invoke ioset ; re-direct the ol' i/o
dont_set_io: ;AN041;
;
; Check for /?. Certain commands, flagged fLimitHelp,
; respond to /? only if it is the only command-line argument.
;
mov ax,[COMSW] ; AX = switches after command
or ax,[ALLSWITCH] ; AX = all switches
and ax,SwitchQues
jz drive_check ; /? not in command line
test [CHKDRV],fLimitHelp
jz do_help ; /? allowed in combination
;
; Make sure /? is the only argument on the command line.
;
cmp [arg.argvcnt],2
jne drive_check ; /? not only arg - ignore
;
; Note: this is all the check we need, even against things like /??.
; Our argv parser breaks /?? into two args, /? and ?.
;
do_help:
; DX = ptr to word list of msg #s, terminated by zero word
mov si,dx ; SI = ptr to list of msg #s
mov ax,NO_SUBST ; AL = no subst's code
push ax ; build subst block on stack
next_help_msg:
lodsw ; AX = help msg # or zero
or ax,ax
jz help_done
push ax ; SS:SP = ptr to subst block
; (msg # and no_subst byte)
; We assume DS = SS.
mov dx,sp ; DS:DX = ptr to subst block
invoke Std_PrintF ; display help message
pop ax ; remove msg # from stack
jmp next_help_msg
help_done:
pop ax ; clean up stack
jmp TCommand
drive_check:
test [CHKDRV], fCheckDrive ; did we wanna check those drives?
jz nocheck
mov AL, [PARM1] ; parse_file_descriptor results tell
or AL, [PARM2] ; us whether those drives were OK
cmp AL, -1
jnz nocheck
jmp drvbad
;
; The user may have omitted the space between the command and its arguments.
; We need to copy the remainder of the user's command line into the buffer.
; Note that thisdoes not mess up the arg structure; it points into COMBUF not
; into the command line at 80.
;
nocheck:
call cmd_copy
switcheck:
test [CHKDRV], fSwitchAllowed ; Does the command take switches
jnz realwork ; Yes, process the command
call noswit ; No, check to see if any switches
jnz realwork ; None, process the command
mov msg_disp_class,parse_msg_class ;AN000; set up parse error msg class
MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,BadSwt_ptr ;AN000; get "Invalid switch" message number
jmp CERROR ; Print error and chill out...
realwork:
call BX ; do some real work, at last
; See if we're in a batch CALL command. If we are, reprocess the command line,
; otherwise, go get another command.
Cmd_done:
push cs ; g restore data segment
pop ds ; g
push ds ; g save data segment
mov ds,[resseg] ; g get segment containing call flag
ASSUME ds:resgroup
cmp call_flag, call_in_progress ; G Is a call in progress?
mov call_flag, 0 ; G Either way, reset flag
pop ds ; g get data segment back
jz incall ; G
jmp tcommand ; chill out...
incall:
JMP DOCOM1
noswit:
push di ; Save di
mov di,81h ; di = ptr to command args
mov si,80h ; Get address of length of command args
lodsb ; Load length
mov cl,al ; Move length to cl
xor ch,ch ; Zero ch
mov al,[SWITCHAR] ; al = switch character
cmp al,0 ; Turn off ZF
repnz scasb ; Scan for a switch character and return
pop di ; with ZF set if one was found
ret
EXTERNAL:
ifndef NEC_98
IF IBM
call test_append ; check to see if append installed
je not_barryf ; no - truly external command
jmp append_internal ; yes - go to Barryf code
not_barryf:
ENDIF
else ;NEC_98
call test_append ; check to see if append installed
je not_barryf ; no - truly external command
jmp append_internal ; yes - go to Barryf code
not_barryf:
endif ;NEC_98
MOV [FILTYP],0
MOV DL,[SPECDRV]
MOV [IDLEN],DL
IF IBM
MOV [ROM_CALL],0
PUSH DX
MOV DX,OFFSET TRANGROUP:IDLEN
CALL ROM_SCAN
POP DX
JNC DO_SCAN
INC [ROM_CALL]
JMP short PostSave
DO_SCAN:
ENDIF
IF IBM
PostSave:
ENDIF
;
; when ntvdm execs via GetNextVdmCommand, execpath is already
; fully qualified application name. We know this because the
; vdminfo is filled
;
; Note that EXECPATH_SIZE is used only once(the one we got it from
; CMDGETNEXTCMD bop). And that is why we reset it everytime after
; we have accessed it. For other executables, we do the regular
; search(processing a batch file, for example).
;
; Two pieces of information we got from 32bits:
; (1). the application full path name(in EXECPATH)
; (2). the application file extention type(in EXECEXT_TYPE)
; EXECEXT_TYPE 2 -> .BAT
; 4 -> .EXE
; 8 -> .COM
; >8 -> unknown
; for unknown extention type, we simply launch it because
; (1). DOS doesn't impose any extention on program file.
; (2). If we ever get here, we are sure that the program file
; is a valid DOS executable(otherwise, CreateProcess would
; have failed and we won't have any file to execute).
;
;
xor ax, ax
xchg ax, [EXECPATH_SIZE] ;get and set
or ax, ax ;do we have appname already?
mov ax, [EXECEXT_TYPE] ;
jnz execute_with_type ;yes, No search
MOV DI,OFFSET TRANGROUP:EXECPATH
MOV BYTE PTR [DI],0 ; Initialize to current directory
IF IBM
CMP [ROM_CALL],0
JNZ NeoExecute
ENDIF
invoke path_search ; find the mother (result in execpath)
execute_with_type:
or AX, AX ; did we find anything?
je badcomj45 ; null means no (sob)
cmp AX, 04H ; 04H and 08H are .exe and .com
; sixteen-bit machine ought
jnl execute ; to be able to handle a SIXTEEN-BIT
; DISPLACEMENT!!
jmp batcom ; 02H is .bat
BADCOMJ45:
ifdef BETA3WARN
JMP BADCOM
else
JMP short BADCOM
endif
ASSUME DS:TRANGROUP,ES:TRANGROUP
EXECUTE:
NeoExecute:
invoke IOSET
;M051
; Previously LoadHigh was jumping to the execute label above. This was wrong
;because IOSET was getting invoked twice resulting in 2 sets of redirections.
;After a close, this would still leave one open active resulting in sharing
;errors on subsequent opens of the redirected file.
;
Lh_Execute: ;M051
MOV ES,[TRAN_TPA]
MOV AH,DEALLOC
INT 21h ; Now running in "free" space
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
INC [EXTCOM] ; Indicate external command
MOV [RESTDIR],0 ; Since USERDIR1 is in transient, insure
; this flag value for re-entry to COMMAND
MOV SI,OFFSET TRANGROUP:EXECPATH
MOV DI,OFFSET RESGROUP:SAFEPATHBUFFER
MOV CX,LenMsgOrPathBuf
CLD
LE_copy_loop:
lodsb
stosb
cmp al, 0
je LE_copy_done
loop LE_copy_loop
;; the program name is too long, terminate it with
;; null character. The Exec call will fail and we will print out error message
;; see command1.asm
mov byte ptr es:[di - 1], 0
LE_copy_done:
MOV DI,FCB
MOV SI,DI
MOV CX,052H ; moving (100h-5Ch)/2 = 80h-2Eh
REP MOVSW ; Transfer parameters to resident header
MOV DX,OFFSET RESGROUP:SAFEPATHBUFFER
PUSH ES
POP DS
ASSUME DS:RESGROUP
MOV BX,OFFSET RESGROUP:EXEC_BLOCK
MOV AX,EXEC SHL 8
IF IBM
TEST [ROM_CALL],-1
JZ OK_EXEC
JMP ROM_EXEC
OK_EXEC:
ENDIF
;
; we are now running in free space. anything we do from here on may get
; trashed. Move the stack (also in free space) to allocated space because
; since EXEC restores the stack, somebody may trash what is on the stack.
;
MOV CX,ES
MOV SS,CX
MOV SP,OFFSET DATARES:RStack
ifdef BETA3WARN
%out Take this out before we ship
cmp Beta3Warned, 0
jne NoWarning
mov Beta3Warned, 0ffh
push ax
push cx
push dx
push ds
mov ah, 2ah ; get date
int 21h
cmp cx, 1991
jb nwx
ja bwarn
cmp dh, 4
jb nwx
bwarn:
mov ds, trnseg
assume ds:trangroup
mov dx, offset trangroup:Beta3WarnMsg
mov ah, 9
int 21h
; wait till a key is hit
@@:
mov ah, 6 ; console I/O
mov dl, 0ffh ; Read
int 21h
jz @b
nwx:
pop ds
assume ds:resgroup
pop dx
pop cx
pop ax
NoWarning:
endif
JMP [EXEC_ADDR] ; Jmp to the EXEC in the resident
ASSUME DS:TRANGROUP
BADCOM:
PUSH CS
POP DS
MOV DX,OFFSET TRANGROUP:BADNAM_ptr
CERROR:
INVOKE std_eprintf
JMP TCOMMAND
;
; Prescan converts the input buffer into a canonicalized form. All
; redirections and pipes are removed.
;
PRESCAN: ; Cook the input buffer
ASSUME DS:TRANGROUP,ES:TRANGROUP
XOR CX,CX
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV SI,OFFSET TRANGROUP:COMBUF+2
MOV DI,SI
CountQuotes:
LODSB ; get a byte
CMP AL,22h ; is it a quote?
JNZ CountEnd ; no, try for end of road
INC CH ; bump count
JMP CountQuotes ; go get next char
CountEnd:
CMP AL,13 ; end of road?
JNZ CountQuotes ; no, go back for next char
;;;; IFDEF DBCS 3/3/KK
PUSH CX ; save count
MOV SI,DI ; get back beginning of buffer
KanjiScan:
LODSB ; get a byte
INVOKE TestKanj ; is it a leadin byte
JZ KanjiQuote ; no, check for quotes
ifdef NEC_98
if BUGFIX
cmp byte ptr [si],' '
jb kanjiQuote
endif
endif ;NEC_98
MOV AH,AL ; save leadin
LODSB ; get trailing byte
CMP AX,DB_SPACE ; is it Kanji space
JNZ KanjiScan ; no, go get next
MOV [SI-2],2020h ; replace with spaces
JMP KanjiScan ; go get next char
KanjiQuote:
CMP AL,22h ; beginning of quoted string
JNZ KanjiEnd ; no, check for end
DEC CH ; drop count
JZ KanjiScan ; if count is zero, no quoting
KanjiQuoteLoop:
LODSB ; get next byte
CMP AL,22h ; is it another quote
JNZ KanjiQuoteLoop ; no, get another
DEC CH ; yes, drop count
JMP KanjiScan ; go get next char
KanjiEnd:
CMP AL,13 ; end of line character?
JNZ KanjiScan ; go back to beginning
POP CX ; get back original count
;;;; ENDIF 3/3/KK
MOV SI,DI ; restore pointer to begining
PRESCANLP:
LODSB
;;;; IFDEF DBCS 3/3/KK
INVOKE TESTKANJ
JZ NOTKANJ6
ifdef NEC_98
if BUGFIX
cmp byte ptr [si],' '
jb NOTKANJ6
endif
endif ;NEC_98
MOV [DI],AL
INC DI ; fake STOSB into DS
LODSB ; grab second byte
MOV [DI],AL ; fake stosb into DS
INC DI
INC CL
INC CL
JMP PRESCANLP
NOTKANJ6:
;;;; ENDIF 3/3/KK
CMP AL,'"' ; " character
JNZ TRYGREATER
DEC CH
JZ TRYGREATER
QLOOP:
MOV [DI],AL
INC DI
INC CL
LODSB
CMP AL,'"' ; " character
JNZ QLOOP
DEC CH
TRYGREATER:
CMP AL,rabracket
JNZ NOOUT
;
; We have found a ">" char. We need to see if there is another ">"
; following it.
;
CMP BYTE PTR [SI],al
JNZ NOAPPND
LODSB
INC [RE_OUT_APP] ; Flag >>
NOAPPND:
;
; Now we attempt to find the file name. First, scan off all whitespace
;
INVOKE SCANOFF
CMP AL,labracket ;AN040; was there no filename?
JZ REOUT_ERRSET ;AN040; yes - set up error
CMP AL,0DH
JNZ GOTREOFIL
;
; There was no file present. Set us up at end-of-line.
;
REOUT_ERRSET: ;AN040; set up for an error
mov byte ptr [di], 0dh ; Clobber first ">"
MOV WORD PTR [RE_OUTSTR],09H ; Cause an error later
JMP PRESCANEND
GOTREOFIL:
PUSH DI
MOV DI,OFFSET RESGROUP:RE_OUTSTR
MOV BX,DI
PUSH ES
SETREOUTSTR: ; Get the output redirection name
; MSKK06 07/14/89
push cx ; save cx
mov cx,64+13 ; CX = max string length
SETREOUTSTR_LOOP:
LODSB
CMP AL,0DH
JZ GOTRESTR_J
INVOKE DELIM
JZ GOTRESTR_J
CMP AL,[SWITCHAR]
JZ GOTRESTR_J
CMP AL,'"' ;AN033; Is the character a quote?
JZ PIPEERRSYNJ5_J ;AN033; Yes - get out quick - or system crashes
CMP AL,labracket ;AN002; Is char for input redirection
JZ ABRACKET_TERM ;AN002; yes - end of string
CMP AL,rabracket ;AN002; Is char for output redirection
JNZ NO_ABRACKET ;AN002; no - not end of string
ABRACKET_TERM: ;AN002; have end of string by < or >
DEC SI ;AN002; back up over symbol
MOV AL,BLANK ;AN002; show delimiter as char
GOTRESTR_J:
pop cx ; MSKK06 07/14/89
JMP SHORT GOTRESTR ;AN002; go process it
NO_ABRACKET: ;AN002; NOT AT END OF STRING
STOSB ; store it into resgroup
ifdef DBCS
invoke testkanj
jz @f ; if not lead byte of DBCS
jcxz gotrestr_j ; if no tail byte
lodsb
cmp al,0dh
jz gotrestr_j ; if tail byte does't come and ends
stosb ; copy tail byte
dec cx
@@:
endif
LOOP SETREOUTSTR_LOOP ; MSKK06 07/14/89
jmp GOTRESTR_j
PIPEERRSYNJ5_J:
pop cx ; recover CX
jmp short PIPEERRSYNJ5
NOOUT:
CMP AL,labracket
JNZ CHKPIPE
mov bx,si ; Save loc of "<"
INVOKE SCANOFF
CMP AL,rabracket ;AN040; was there no filename?
JZ REIN_ERRSET ;AN040; yes - set up error
CMP AL,0DH
JNZ GOTREIFIL
REIN_ERRSET: ;AN040; set up for error
mov byte ptr [di],0dh ; Clobber "<"
MOV WORD PTR [RE_INSTR],09H ; Cause an error later
JMP SHORT PRESCANEND
GOTREIFIL:
PUSH DI
MOV DI,OFFSET TranGROUP:RE_INSTR
MOV BX,DI
PUSH ES
PUSH CS
POP ES ; store in TRANGROUP
JMP SHORT SETREOUTSTR ; Get the input redirection name
CHKPIPE:
MOV AH,AL
CMP AH,AltPipeChr
JZ IsPipe3
CMP AH,vbar
JNZ CONTPRESCAN
IsPipe3:
;
; Only push the echo flag if we are entering the pipe for the first time.
;
CMP PipeFlag,0
JNZ NoEchoPush
SHL EchoFlag,1 ; push echo state and turn it off
NoEchoPush:
INC [PIPEFLAG]
INVOKE SCANOFF
CMP AL,0DH
JZ PIPEERRSYNJ5
CMP AL,AltPipeChr
JZ PIPEERRSYNJ5
CMP AL,vbar ; Double '|'?
JNZ CONTPRESCAN
PIPEERRSYNJ5:
PUSH ES
POP DS ; DS->RESGROUP
JMP PIPEERRSYN
;
; Trailing :s are allowed on devices. Check to be sure that there is more
; than just a : in the redir string.
;
GOTRESTR:
XCHG AH,AL
mov al,':'
SUB BX,DI ; compute negatinve of number of chars
CMP BX,-1 ; is there just a :?
JZ NotTrailCol ; yep, don't change
CMP BYTE PTR ES:[DI-1],al ; Trailing ':' OK on devices
JNZ NOTTRAILCOL
DEC DI ; Back up over trailing ':'
NOTTRAILCOL:
XOR AL,AL
STOSB ; NUL terminate the string
POP ES
POP DI ; Remember the start
CONTPRESCAN:
MOV [DI],AH ; "delete" the redirection string
INC DI
CMP AH,0DH
JZ PRESCANEND
INC CL
JMP PRESCANLP
PRESCANEND:
CMP [PIPEFLAG],0
JZ ISNOPIPE
MOV DI,OFFSET RESGROUP:PIPESTR
MOV [PIPEPTR],DI
MOV SI,OFFSET TRANGROUP:COMBUF+2
INVOKE SCANOFF
PIPESETLP: ; Transfer the pipe into the resident
LODSB ; pipe buffer
STOSB
CMP AL,0DH
JNZ PIPESETLP
ISNOPIPE:
MOV [COMBUF+1],CL
CMP [PIPEFLAG],0
PUSH CS
POP ES
return
cmd_copy proc near
MOV SI,OFFSET TRANGROUP:COMBUF+2
INVOKE Scanoff ; advance past separators...
add si,PathPos
mov di,81h
xor cx,cx
CmdCopy:
lodsb
stosb
cmp al,0dh
jz CopyDone
inc cx
jmp CmdCopy
CopyDone:
mov byte ptr ds:[80h],cl ; Store count
ret
cmd_copy endp
test_append proc near
mov BX,offset TRANGROUP:COMBUF ; barry can address
mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set
mov DX,-1 ; set install check function
mov AX,0AE00H
int 2FH ; see if loaded
cmp AL,00H
ret
test_append endp
TRANCODE ENDS
END