MS-DOS/v2.0/source/TCODE.ASM

1088 lines
33 KiB
NASM
Raw Normal View History

1983-08-13 01:53:34 +01:00
TITLE PART1 - COMMAND Transient routines.
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
DATARES SEGMENT PUBLIC
EXTRN BATCH:WORD,BATLOC:DWORD,PARMBUF:BYTE
EXTRN RESTDIR:BYTE,EXTCOM:BYTE,ECHOFLAG:BYTE
EXTRN SINGLECOM:WORD,VERVAL:WORD,FORFLAG:BYTE
EXTRN RE_INSTR:BYTE,RE_OUT_APP:BYTE,PIPE1:BYTE,PIPE2:BYTE
EXTRN RE_OUTSTR:BYTE,PIPEFLAG:BYTE,PIPEFILES:BYTE,PIPEPTR:WORD
EXTRN INPIPEPTR:WORD,OUTPIPEPTR:WORD,EXEC_BLOCK:BYTE,ENVIRSEG:WORD
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN BADBAT:BYTE,NEEDBAT:BYTE,BADNAM:BYTE
EXTRN SYNTMES:BYTE,BADDRV:BYTE,BYTMES_POST:BYTE
EXTRN DIRMES_PRE:BYTE,DIRMES_POST:BYTE,BYTMES_PRE:BYTE
EXTRN NOTFND:BYTE,PIPEEMES:BYTE,BADPMES:BYTE,COMTAB:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN UCOMBUF:BYTE,COMBUF:BYTE,USERDIR1:BYTE,EXECPATH:BYTE
EXTRN DIRCHAR:BYTE,EXEC_ADDR:DWORD,RCH_ADDR:DWORD,CHKDRV:BYTE
EXTRN CURDRV:BYTE,PARM1:BYTE,PARM2:BYTE,COMSW:WORD,ARG1S:WORD
EXTRN ARG2S:WORD,ARGTS:WORD,SPECDRV:BYTE,BYTCNT:WORD,IDLEN:BYTE
EXTRN DIRBUF:BYTE,ID:BYTE,COM:BYTE,LINCNT:BYTE,INTERNATVARS:BYTE
EXTRN HEADCALL:DWORD,RESSEG:WORD,TPA:WORD,SWITCHAR:BYTE
EXTRN STACK:WORD,FILTYP:BYTE,FILECNT:WORD,LINLEN:BYTE
IF KANJI
EXTRN KPARSE:BYTE
ENDIF
TRANSPACE ENDS
; ********************************************************************
; START OF TRANSIENT PORTION
; This code is loaded at the end of memory and may be overwritten by
; memory-intensive user programs.
TRANCODE SEGMENT PUBLIC PARA
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN SCANOFF:NEAR,DELIM:NEAR,SAVUDIR:NEAR,SAVUDIR1:NEAR
EXTRN PATHCHRCMP:NEAR,PRINT:NEAR,RESTUDIR:NEAR
EXTRN CRLF2:NEAR,PRINT_PROMPT:NEAR,GETBATBYT:NEAR,PRESCAN:NEAR
EXTRN CRPRINT:NEAR,DISP32BITS:NEAR,FCB_TO_ASCZ:NEAR
EXTRN ERROR_PRINT:NEAR,FREE_TPA:NEAR,ALLOC_TPA:NEAR
EXTRN $EXIT:NEAR,FORPROC:NEAR,FIND_NAME_IN_ENVIRONMENT:NEAR
EXTRN UPCONV:NEAR,BATOPEN:NEAR,BATCLOSE:NEAR,IOSET:NEAR,FIND_PATH:NEAR
EXTRN TESTDOREIN:NEAR,TESTDOREOUT:NEAR
PUBLIC SWLIST,CERROR,SETREST1,DOCOM,DOCOM1,DRVBAD,NOTFNDERR
PUBLIC COMMAND,TCOMMAND,SWITCH,PIPEERRSYN,GETKEYSTROKE,SETREST
PUBLIC CHKCNT
IF KANJI
EXTRN TESTKANJ:NEAR
ENDIF
ORG 0
ZERO = $
ORG 100H ; Allow for 100H parameter area
SETDRV:
MOV AH,SET_DEFAULT_DRIVE
INT int_command
TCOMMAND:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV AX,-1
XCHG AX,[VERVAL]
CMP AX,-1
JZ NOSETVER2
MOV AH,SET_VERIFY_ON_WRITE ; AL has correct value
INT int_command
NOSETVER2:
CALL [HEADCALL] ; Make sure header fixed
XOR BP,BP ; Flag transient not read
CMP [SINGLECOM],-1
JNZ COMMAND
$EXITPREP:
PUSH CS
POP DS
JMP $EXIT ; Have finished the single command
ASSUME DS:NOTHING
COMMAND:
CLD
MOV AX,CS
MOV SS,AX
ASSUME SS:TRANGROUP
MOV SP,OFFSET TRANGROUP:STACK
MOV ES,AX
ASSUME ES:TRANGROUP
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
STI
MOV [UCOMBUF],COMBUFLEN ; Init UCOMBUF
MOV [COMBUF],COMBUFLEN ; Init COMBUF (Autoexec doing DATE)
OR BP,BP ; See if just read
JZ TESTRDIR ; Not read, check user directory
MOV WORD PTR [UCOMBUF+1],0D01H ; Reset buffer
JMP SHORT NOSETBUF
TESTRDIR:
CMP [RESTDIR],0
JZ NOSETBUF ; User directory OK
PUSH DS
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV DX,OFFSET TRANGROUP:USERDIR1
MOV AH,CHDIR
INT int_command ; Restore users directory
POP DS
ASSUME DS:RESGROUP
NOSETBUF:
CMP [PIPEFILES],0
JZ NOPCLOSE ; Don't bother if they don't exist
CMP [PIPEFLAG],0
JNZ NOPCLOSE ; Don't del if still piping
CALL PIPEDEL
NOPCLOSE:
MOV [EXTCOM],0 ; Flag internal command
MOV [RESTDIR],0 ; Flag users dirs OK
MOV AX,CS ; Get segment we're in
MOV DS,AX
ASSUME DS:TRANGROUP
PUSH AX
MOV DX,OFFSET TRANGROUP:INTERNATVARS
MOV AX,INTERNATIONAL SHL 8
INT 21H
POP AX
SUB AX,[TPA] ; AX=size of TPA in paragraphs
MOV DX,16
MUL DX ; DX:AX=size of TPA in bytes
OR DX,DX ; See if over 64K
JZ SAVSIZ ; OK if not
MOV AX,-1 ; If so, limit to 65535 bytes
SAVSIZ:
MOV [BYTCNT],AX ; Max no. of bytes that can be buffered
MOV DS,[RESSEG] ; All batch work must use resident seg.
ASSUME DS:RESGROUP
TEST [ECHOFLAG],-1
JZ GETCOM ; Don't do the CRLF
CALL SINGLETEST
JB GETCOM
CALL CRLF2
GETCOM:
MOV AH,GET_DEFAULT_DRIVE
INT int_command
MOV [CURDRV],AL
TEST [ECHOFLAG],-1
JZ NOPDRV ; No prompt if echo off
CALL SINGLETEST
JB NOPDRV
CALL PRINT_PROMPT ; Prompt the user
NOPDRV:
TEST [PIPEFLAG],-1 ; Pipe has highest presedence
JZ NOPIPE
JMP PIPEPROC ; Continue the pipeline
NOPIPE:
TEST [FORFLAG],-1 ; FOR has next highest precedence
JZ TESTFORBAT
JMP FORPROC ; Continue the FOR
TESTFORBAT:
MOV [RE_INSTR],0 ; Turn redirection back off
MOV [RE_OUTSTR],0
MOV [RE_OUT_APP],0
TEST [BATCH],-1 ; Batch has lowest precedence
JZ ISNOBAT
JMP READBAT ; Continue BATCH
ISNOBAT:
CMP [SINGLECOM],0
JZ REGCOM
MOV SI,-1
XCHG SI,[SINGLECOM]
MOV DI,OFFSET TRANGROUP:COMBUF + 2
XOR CX,CX
SINGLELOOP:
LODSB
STOSB
INC CX
CMP AL,0DH
JNZ SINGLELOOP
DEC CX
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV [COMBUF + 1],CL
JMP DOCOM
REGCOM:
PUSH CS
POP DS ; Need local segment to point to buffer
MOV DX,OFFSET TRANGROUP:UCOMBUF
MOV AH,STD_CON_STRING_INPUT
INT int_command ; Get a command
MOV CL,[UCOMBUF]
XOR CH,CH
ADD CX,3
MOV SI,OFFSET TRANGROUP:UCOMBUF
MOV DI,OFFSET TRANGROUP:COMBUF
REP MOVSB ; Transfer it to the cooked buffer
JMP DOCOM
; All batch proccessing has DS set to segment of resident portion
ASSUME DS:RESGROUP,ES:TRANGROUP
NEEDENV:
PUSH DS
PUSH SI
PUSH DI
MOV DI,OFFSET TRANGROUP:ID
ADD AL,"0"
STOSB
GETENV1:
CALL GETBATBYT
STOSB
CMP AL,13
JZ GETENV2
CMP AL,"%"
JNZ GETENV1
MOV BYTE PTR ES:[DI-1],"="
GETENV2:
MOV SI,OFFSET TRANGROUP:ID
PUSH CS
POP DS ; DS:SI POINTS TO NAME
ASSUME DS:TRANGROUP,ES:RESGROUP
CALL FIND_NAME_IN_environment
PUSH ES
POP DS
PUSH CS
POP ES
ASSUME DS:RESGROUP,ES:TRANGROUP
MOV SI,DI
POP DI ; get back pointer to command line
JNC GETENV4
GETENV3: ; Parameter not found
PUSH CS
POP DS
MOV SI,OFFSET TRANGROUP:ID
GETENV4:
LODSB ; From resident segment
OR AL,AL ; Check for end of parameter
JZ GETENV6
CMP AL,13
JZ GETENV6
CMP AL,"="
JZ GETENVX
STOSB
JMP GETENV4
GETENVX:
MOV AL,"%"
STOSB
GETENV6:
POP SI
POP DS
CMP AL,13
JZ SAVBATBYTJ
JMP RDBAT
NEEDPARM:
CALL GETBATBYT
CMP AL,"%" ; Check for two consecutive %
JZ SAVBATBYTJ
CMP AL,13 ; Check for end-of-line
JNZ PAROK
SAVBATBYTJ:
JMP SAVBATBYT
PAROK:
SUB AL,"0"
JB NEEDENV ; look for parameter in the environment
CMP AL,9
JA NEEDENV
CBW
MOV SI,AX
SHL SI,1 ; Two bytes per entry
PUSH ES
PUSH DI
MOV ES,[BATCH]
XOR CX,CX
MOV AX,CX
MOV DI,CX
DEC CX
REPNZ SCASB
ADD DI,SI
MOV SI,ES:[DI]
POP DI
POP ES
CMP SI,-1 ; Check if parameter exists
JZ RDBAT ; Ignore if it doesn't
RDPARM:
LODSB ; From resident segment
CMP AL,0DH ; Check for end of parameter
JZ RDBAT
STOSB
JMP RDPARM
PROMPTBAT:
MOV DX,OFFSET TRANGROUP:NEEDBAT
CALL [RCH_ADDR]
JZ AskForBat ; Media is removable
NoAskForBat:
MOV ES,[BATCH] ; Turn off batch
MOV AH,DEALLOC
INT int_command ; free up the batch piece
MOV [BATCH],0 ; AFTER DEALLOC in case of ^C
MOV [FORFLAG],0 ; Turn off for processing
MOV [PIPEFLAG],0 ; Turn off any pipe
PUSH CS
POP DS
MOV DX,OFFSET TRANGROUP:BADBAT
CALL ERROR_PRINT ; Tell user no batch file
JMP TCOMMAND
ASKFORBAT:
PUSH CS
POP DS
CALL ERROR_PRINT ; Prompt for batch file
CALL GetKeystroke
JMP TCOMMAND
;**************************************************************************
; read the next keystroke
GetKeystroke:
MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR STD_CON_INPUT_no_echo
INT int_command ; Get character with KB buffer flush
MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0
INT int_command
return
READBAT:
CALL BATOPEN
JC PROMPTBAT
MOV DI,OFFSET TRANGROUP:COMBUF+2
TESTNOP:
CALL GETBATBYT
CMP AL,':' ; Label/Comment?
JNZ NOTLABEL
NOPLINE: ; Consume the line
CALL GETBATBYT
CMP AL,0DH
JNZ NOPLINE
CALL GETBATBYT ; Eat Linefeed
TEST [BATCH],-1
JNZ TESTNOP
JMP TCOMMAND ; Hit EOF
RDBAT:
CALL GETBATBYT
NOTLABEL:
CMP AL,"%" ; Check for parameter
JNZ SAVBATBYT
JMP NEEDPARM
SAVBATBYT:
STOSB
CMP AL,0DH
JNZ RDBAT
SUB DI,OFFSET TRANGROUP:COMBUF+3
MOV AX,DI
MOV ES:[COMBUF+1],AL ; Set length of line
CALL GETBATBYT ; Eat linefeed
CALL BATCLOSE
TEST [ECHOFLAG],-1
PUSH CS
POP DS ; Go back to local segment
JZ NOECHO2
ASSUME DS:TRANGROUP
MOV DX,OFFSET TRANGROUP:COMBUF+2
CALL CRPRINT
DOCOM:
; All segments are local for command line processing
CALL CRLF2
DOCOM1:
NOECHO2:
CALL PRESCAN ; Cook the input buffer
JZ NOPIPEPROC
JMP PIPEPROCSTRT ; Fire up the pipe
NOPIPEPROC:
MOV SI,OFFSET TRANGROUP:COMBUF+2
MOV DI,OFFSET TRANGROUP:IDLEN
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H ; Make FCB with blank scan-off
INT int_command
CMP AL,1 ; Check for ambiguous command name
JZ BADCOMJ1 ; Ambiguous commands not allowed
CMP AL,-1
JNZ DRVGD
JMP DRVBAD
BADCOMJ1:
JMP BADCOM
DRVGD:
MOV AL,[DI]
MOV [SPECDRV],AL
MOV AL," "
MOV CX,9
INC DI
REPNE SCASB ; Count no. of letters in command name
MOV AL,9
SUB AL,CL
MOV [IDLEN],AL
MOV DI,81H
XOR CX,CX
PUSH SI
COMTAIL:
LODSB
STOSB ; Move command tail to 80H
CMP AL,13
LOOPNZ COMTAIL
NOT CL
MOV BYTE PTR DS:[80H],CL
POP SI
; If the command has 0 parameters must check here for
; any switches that might be present.
; SI -> first character after the command.
CALL SWITCH ; Is the next character a SWITCHAR
MOV [COMSW],AX
MOV DI,FCB
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H
INT int_command
MOV [PARM1],AL ; Save result of parse
PRBEG:
LODSB
CMP AL,[SWITCHAR]
JZ PRFIN
CMP AL,13
JZ PRFIN
CALL DELIM
JNZ PRBEG
PRFIN:
DEC SI
CALL SWITCH
MOV [ARG1S],AX
MOV DI,FCB+10H
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H
INT int_command ; Parse file name
MOV [PARM2],AL ; Save result
CALL SWITCH
MOV [ARG2S],AX
OR AX,[ARG1S]
MOV [ARGTS],AX
SWTLP: ; Find any remaining switches
CMP BYTE PTR [SI],0DH
JZ GOTALLSW
INC SI
CALL SWITCH
OR [ARGTS],AX
JMP SHORT SWTLP
GOTALLSW:
MOV AL,[IDLEN]
MOV DL,[SPECDRV]
OR DL,DL ; Check if drive was specified
JZ OK
JMP DRVCHK
OK:
DEC AL ; Check for null command
JNZ FNDCOM
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
CMP [SINGLECOM],-1
JZ EXITJ
JMP GETCOM
EXITJ:
JMP $EXITPREP
ASSUME DS:TRANGROUP
RETSW:
XCHG AX,BX ; Put switches in AX
return
SWITCH:
XOR BX,BX ; Initialize - no switches set
SWLOOP:
CALL SCANOFF ; Skip any delimiters
CMP AL,[SWITCHAR] ; Is it a switch specifier?
JNZ RETSW ; No -- we're finished
OR BX,GOTSWITCH ; Indicate there is a switch specified
INC SI ; Skip over the switch character
CALL SCANOFF
CMP AL,0DH
JZ RETSW ; Oops
INC SI
; Convert lower case input to upper case
CALL UPCONV
MOV DI,OFFSET TRANGROUP:SWLIST
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
SWLIST DB "VBAPW"
SWCOUNT EQU $-SWLIST
DRVBAD:
MOV DX,OFFSET TRANGROUP:BADDRV
JMP CERROR
FNDCOM:
MOV SI,OFFSET TRANGROUP:COMTAB ; Prepare to search command table
MOV CH,0
FINDCOM:
MOV DI,OFFSET TRANGROUP:IDLEN
MOV CL,[SI]
JCXZ EXTERNAL
REPE CMPSB
LAHF
ADD SI,CX ; Bump to next position without affecting flags
SAHF
LODSB ; Get flag for drive check
MOV [CHKDRV],AL
LODSW ; Get address of command
JNZ FINDCOM
MOV DX,AX
CMP [CHKDRV],0
JZ NOCHECK
MOV AL,[PARM1]
OR AL,[PARM2] ; Check if either parm. had invalid drive
CMP AL,-1
JZ DRVBAD
NOCHECK:
CALL IOSET
CALL DX ; Call the internal
COMJMP:
JMP TCOMMAND
SETDRV1:
JMP SETDRV
DRVCHK:
DEC DL ; Adjust for correct drive number
DEC AL ; Check if anything else is on line
JZ SETDRV1
EXTERNAL:
MOV [FILTYP],0
MOV DL,[SPECDRV]
MOV [IDLEN],DL
CALL SAVUDIR ; Drive letter already checked
MOV AL,'?'
MOV DI,OFFSET TRANGROUP:COM
STOSB ; Look for any extension
STOSB
STOSB
MOV DX,OFFSET TRANGROUP:DIRBUF ; Command will end up here
MOV AH,SET_DMA
INT int_command
PUSH ES
CALL FIND_PATH
MOV SI,DI
POP ES
MOV DI,OFFSET TRANGROUP:EXECPATH
MOV BYTE PTR [DI],0 ; Initialize to current directory
RESEARCH:
MOV AH,DIR_SEARCH_FIRST
COMSRCH:
PUSH CS
POP DS
MOV DX,OFFSET TRANGROUP:IDLEN
INT int_command
OR AL,AL
MOV AH,DIR_SEARCH_NEXT ; Do search-next next
JNZ PATHCHK
CMP WORD PTR [DIRBUF+9],4F00H + "C"
JNZ CHKEXE
CMP [DIRBUF+11],"M"
JNZ CHKEXE
OR [FILTYP],4
JMP EXECUTE ; If we find a COM were done
CHKEXE:
CMP WORD PTR [DIRBUF+9],5800H + "E"
JNZ CHKBAT
CMP [DIRBUF+11],"E"
JNZ CHKBAT
OR [FILTYP],1 ; Flag an EXE found
JMP COMSRCH ; Continue search
CHKBAT:
CMP WORD PTR [DIRBUF+9],4100H + "B"
JNZ COMSRCH
CMP [DIRBUF+11],"T"
JNZ COMSRCH
OR [FILTYP],2 ; Flag BAT found
JMP COMSRCH ; Continue search
PATHCHK:
TEST [FILTYP],1
JZ TESTBAT
MOV WORD PTR [DIRBUF+9],5800H+"E"
MOV [DIRBUF+11],"E"
JMP EXECUTE ; Found EXE
TESTBAT:
TEST [FILTYP],2
JZ NEXTPATH ; Found nothing, try next path
MOV WORD PTR [DIRBUF+9],4100H+"B"
MOV [DIRBUF+11],"T"
MOV DX,OFFSET TRANGROUP:DIRBUF ; Found BAT
MOV AH,FCB_OPEN
INT int_command
OR AL,AL
JZ BATCOMJ ; Bat exists
CALL RESTUDIR
JMP BADCOM
BATCOMJ:
JMP BATCOM
NEXTPATH:
MOV DX,OFFSET TRANGROUP:USERDIR1 ; Restore users dir
MOV AH,CHDIR
INT int_command
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV [RESTDIR],0
BADPATHEL:
MOV DI,OFFSET TRANGROUP:EXECPATH ; Build a full path here
MOV DX,SI
MOV DS,[ENVIRSEG] ; Point into environment
ASSUME DS:NOTHING
LODSB
IF KANJI
MOV [KPARSE],0
ENDIF
OR AL,AL
JZ BADCOMJ ; NUL, command not found
XOR BL,BL ; Make BL a NUL
PSKIPLP: ; Get the path
STOSB
OR AL,AL
JZ LASTPATH
CMP AL,';'
JZ GOTNEXTPATH
CMP DI,15+DirStrLen+(OFFSET TRANGROUP:EXECPATH)
JB OKPath
SKIPPathElem:
LODSB ; scan to end of path element
OR AL,AL
JZ BadPathEl
CMP AL,';'
JZ BadPathEl
JMP SkipPathElem
OKPath:
IF KANJI
MOV [KPARSE],0
CALL TESTKANJ
JZ NXTPTCHR
INC [KPARSE]
MOVSB
NXTPTCHR:
ENDIF
LODSB
JMP SHORT PSKIPLP
BADCOMJ:
JMP BADCOM
LASTPATH:
MOV BYTE PTR ES:[DI-1],';' ; Fix up the NUL in EXECPATH
DEC SI ; Point to the NUL in PATHSTRING
MOV BL,[SI-1] ; Change substi char to char before NUL
GOTNEXTPATH:
DEC DI ; Point to the end of the dir
PUSH BX
PUSH SI
PUSH DX
MOV SI,DX
XOR DL,DL
CMP BYTE PTR [SI+1],DRVCHAR
JNZ DEFDRVPATH ; No drive spec
MOV DL,[SI]
SUB DL,'@'
DEFDRVPATH:
PUSH DS
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV [IDLEN],DL ; New drive
PUSH DI
CALL SAVUDIR ; Save the users dir
POP DI
JNC PATHTRY
MOV DX,OFFSET TRANGROUP:BADPMES ; Tell the user bad stuff in path
CALL PRINT
PATHTRY:
POP DS
ASSUME DS:NOTHING
POP DX
POP SI
POP BX
XCHG BL,[SI-1] ; Stick in NUL, or same thing if LASTPATH
CDPATH:
MOV AH,CHDIR
INT int_command
MOV [SI-1],BL ; Fix the path string back up
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
INC [RESTDIR] ; Say users dir needs restoring
JNC ResearchJ
JMP BADPATHEL ; Ignore a directory which doesn't exist
ResearchJ:
JMP RESEARCH ; Try looking in this one
BATCOM:
ASSUME DS:TRANGROUP
; Batch parameters are read with ES set to segment of resident part
CALL IOSET ; Set up any redirection
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
;Since BATCH has lower precedence than PIPE or FOR. If a new BATCH file
;is being started it MUST be true that no FOR or PIPE is currently in
;progress.
MOV [FORFLAG],0 ; Turn off for processing
MOV [PIPEFLAG],0 ; Turn off any pipe
TEST [BATCH],-1
JNZ CHAINBAT ; Don't need allocation if chaining
CALL FREE_TPA
ASSUME ES:RESGROUP
MOV BX,6 ; 64 + 32 bytes
MOV AH,ALLOC
INT int_command ; Suck up a little piece for batch processing
MOV [BATCH],AX
CALL ALLOC_TPA
CHAINBAT:
PUSH ES
MOV ES,[BATCH]
ASSUME ES:NOTHING
MOV DL,[DIRBUF]
XOR DI,DI
CALL SAVUDIR1 ; ES:DI set up, get dir containing Batch file
XOR AX,AX
MOV CX,AX
DEC CX
REPNZ SCASB ; Find the NUL
DEC DI ; Point at the NUL
MOV AL,[DIRCHAR]
CMP AL,ES:[DI-1]
JZ NOPUTSLASH
STOSB
NOPUTSLASH:
MOV SI,OFFSET TRANGROUP:DIRBUF+1
CALL FCB_TO_ASCZ ; Tack on batch file name
MOV AX,-1
MOV BX,DI
MOV CX,10
REP STOSW ; Init Parmtab to no parms
POP ES
ASSUME ES:RESGROUP
CALL RESTUDIR
MOV SI,OFFSET TRANGROUP:COMBUF+2
MOV DI,OFFSET RESGROUP:PARMBUF
MOV CX,10
EACHPARM:
CALL SCANOFF
CMP AL,0DH
JZ HAVPARM
JCXZ MOVPARM ; Only first 10 parms get pointers
PUSH ES
MOV ES,[BATCH]
MOV ES:[BX],DI ; Set pointer table to point to actual parameter
POP ES
INC BX
INC BX
MOVPARM:
LODSB
CALL DELIM
JZ ENDPARM ; Check for end of parameter
STOSB
CMP AL,0DH
JZ HAVPARM
JMP SHORT MOVPARM
ENDPARM:
MOV AL,0DH
STOSB ; End-of-parameter marker
JCXZ EACHPARM
DEC CX
JMP SHORT EACHPARM
HAVPARM:
XOR AL,AL
STOSB ; Nul terminate the parms
XOR AX,AX
PUSH ES
POP DS ; Simply batch FCB setup
ASSUME DS:RESGROUP
MOV WORD PTR [BATLOC],AX ; Start at beginning of file
MOV WORD PTR [BATLOC+2],AX
CMP [SINGLECOM],-1
JNZ NOBATSING
MOV [SINGLECOM],0FFF0H ; Flag single command BATCH job
NOBATSING:
JMP TCOMMAND
ASSUME DS:TRANGROUP,ES:TRANGROUP
EXECUTE:
CALL RESTUDIR
NeoExecute:
CMP BYTE PTR [DI],0 ; Command in current directory
JZ NNSLSH
MOV AL,[DI-1]
IF KANJI
CMP [KPARSE],0
JNZ StuffPath ; Last char is second KANJI byte, might be '\'
ENDIF
CALL PATHCHRCMP
JZ HAVEXP ; Don't double slash
StuffPath:
MOV AL,[DIRCHAR]
STOSB
JMP SHORT HAVEXP
NNSLSH:
MOV AL,[DIRBUF] ; Specify a drive
ADD AL,'@'
STOSB
MOV AL,DRVCHAR
STOSB
HAVEXP:
MOV SI,OFFSET TRANGROUP:DIRBUF+1
CALL FCB_TO_ASCZ ; Tack on the filename
CALL IOSET
MOV ES,[TPA]
MOV AH,DEALLOC
INT int_command ; 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 DI,FCB
MOV SI,DI
MOV CX,052H
REP MOVSW ; Transfer parameters to resident header
MOV DX,OFFSET TRANGROUP:EXECPATH
MOV BX,OFFSET RESGROUP:EXEC_BLOCK
MOV AX,EXEC SHL 8
JMP [EXEC_ADDR] ; Jmp to the EXEC in the resident
BADCOM:
PUSH CS
POP DS
MOV DX,OFFSET TRANGROUP:BADNAM
CERROR:
CALL ERROR_PRINT
JMP TCOMMAND
SINGLETEST:
ASSUME DS:RESGROUP
CMP [SINGLECOM],0
JZ RET5
CMP [SINGLECOM],0EFFFH
return
ASSUME DS:TRANGROUP
SETREST1:
MOV AL,1
SETREST:
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV [RESTDIR],AL
POP DS
ASSUME DS:TRANGROUP
RET5:
return
CHKCNT:
TEST [FILECNT],-1
JNZ ENDDIR
NOTFNDERR:
MOV DX,OFFSET TRANGROUP:NOTFND
JMP CERROR
ENDDIR:
; Make sure last line ends with CR/LF
MOV AL,[LINLEN]
CMP AL,[LINCNT] ; Will be equal if just had CR/LF
JZ MESSAGE
CALL CRLF2
MESSAGE:
MOV DX,OFFSET TRANGROUP:DIRMES_PRE
CALL PRINT
MOV SI,[FILECNT]
XOR DI,DI
CALL DISP32BITS
MOV DX,OFFSET TRANGROUP:DIRMES_POST
CALL PRINT
MOV AH,GET_DRIVE_FREESPACE
MOV DL,BYTE PTR DS:[FCB]
INT int_command
CMP AX,-1
retz
MOV DX,OFFSET TRANGROUP:BYTMES_PRE
CALL PRINT
MUL CX ; AX is bytes per cluster
MUL BX
MOV DI,DX
MOV SI,AX
CALL DISP32BITS
MOV DX,OFFSET TRANGROUP:BYTMES_POST
JMP PRINT
ASSUME DS:RESGROUP
PIPEDEL:
PUSH DX
MOV DX,OFFSET RESGROUP:PIPE1 ; Clean up in case ^C
MOV AH,UNLINK
INT int_command
MOV DX,OFFSET RESGROUP:PIPE2
MOV AH,UNLINK
INT int_command
XOR AX,AX
MOV WORD PTR [PIPEFLAG],AX ; Pipe files and pipe gone
MOV [ECHOFLAG],1 ; Make sure ^C to pipe doesn't leave ECHO OFF
POP DX
return
PIPEERRSYN:
MOV DX,OFFSET TRANGROUP:SYNTMES
JMP SHORT PIPPERR
PIPEERR:
MOV DX,OFFSET TRANGROUP:PIPEEMES
PIPPERR:
CALL PIPEDEL
PUSH CS
POP DS
JMP CERROR
PIPEPROCSTRT:
ASSUME DS:TRANGROUP,ES:TRANGROUP
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
INC [PIPEFILES] ; Flag that the pipe files exist
MOV AH,19H ; Get current drive
INT int_command
ADD AL,'A'
MOV [PIPE2],AL ; Make pipe files in root of def drv
MOV BX,OFFSET RESGROUP:PIPE1
MOV [BX],AL
MOV DX,BX
XOR CX,CX
MOV AH,CREAT
INT int_command
JC PIPEERR ; Couldn't create
MOV BX,AX
MOV AH,CLOSE ; Don't proliferate handles
INT int_command
MOV DX,OFFSET RESGROUP:PIPE2
MOV AH,CREAT
INT int_command
JC PIPEERR
MOV BX,AX
MOV AH,CLOSE
INT int_command
CALL TESTDOREIN ; Set up a redirection if specified
MOV [ECHOFLAG],0 ; No echo on pipes
MOV SI,[PIPEPTR]
CMP [SINGLECOM],-1
JNZ NOSINGP
MOV [SINGLECOM],0F000H ; Flag single command pipe
NOSINGP:
JMP SHORT FIRSTPIPE
PIPEPROC:
ASSUME DS:RESGROUP
MOV [ECHOFLAG],0 ; No echo on pipes
MOV SI,[PIPEPTR]
LODSB
CMP AL,'|'
JNZ PIPEEND ; Pipe done
MOV DX,[INPIPEPTR] ; Get the input file name
MOV AX,(OPEN SHL 8)
INT int_command
PIPEERRJ:
JC PIPEERR ; Lost the pipe file
MOV BX,AX
MOV AL,0FFH
XCHG AL,[BX.PDB_JFN_Table]
MOV DS:[PDB_JFN_Table],AL ; Redirect
FIRSTPIPE:
MOV DI,OFFSET TRANGROUP:COMBUF + 2
XOR CX,CX
CMP BYTE PTR [SI],0DH ; '|<CR>'
JNZ PIPEOK1
PIPEERRSYNJ:
JMP PIPEERRSYN
PIPEOK1:
CMP BYTE PTR [SI],'|' ; '||'
JZ PIPEERRSYNJ
PIPECOMLP:
LODSB
STOSB
IF KANJI
CALL TESTKANJ
JZ NOTKANJ5
MOVSB
JMP PIPECOMLP
NOTKANJ5:
ENDIF
CMP AL,0DH
JZ LASTPIPE
INC CX
CMP AL,'|'
JNZ PIPECOMLP
MOV BYTE PTR ES:[DI-1],0DH
DEC CX
MOV [COMBUF+1],CL
DEC SI
MOV [PIPEPTR],SI ; On to next pipe element
MOV DX,[OUTPIPEPTR]
PUSH CX
XOR CX,CX
MOV AX,(CREAT SHL 8)
INT int_command
POP CX
JC PIPEERRJ ; Lost the file
MOV BX,AX
MOV AL,0FFH
XCHG AL,[BX.PDB_JFN_Table]
MOV DS:[PDB_JFN_Table+1],AL
XCHG DX,[INPIPEPTR] ; Swap for next element of pipe
MOV [OUTPIPEPTR],DX
JMP SHORT PIPECOM
LASTPIPE:
MOV [COMBUF+1],CL
DEC SI
MOV [PIPEPTR],SI ; Point at the CR (anything not '|' will do)
CALL TESTDOREOUT ; Set up the redirection if specified
PIPECOM:
PUSH CS
POP DS
JMP NOPIPEPROC ; Process the pipe element
PIPEEND:
CALL PIPEDEL
CMP [SINGLECOM],0F000H
JNZ NOSINGP2
MOV [SINGLECOM],-1 ; Make it return
NOSINGP2:
JMP TCOMMAND
TRANCODE ENDS
END