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/TCODE.ASM | 540 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 540 insertions(+) create mode 100644 v4.0/src/CMD/COMMAND/TCODE.ASM (limited to 'v4.0/src/CMD/COMMAND/TCODE.ASM') diff --git a/v4.0/src/CMD/COMMAND/TCODE.ASM b/v4.0/src/CMD/COMMAND/TCODE.ASM new file mode 100644 index 0000000..17ad82d --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCODE.ASM @@ -0,0 +1,540 @@ + page 80,132 +; SCCSID = @(#)tcode.asm 1.1 85/05/14 +; SCCSID = @(#)tcode.asm 1.1 85/05/14 +TITLE Part1 COMMAND Transient Routines + + INCLUDE comsw.asm +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +CODERES SEGMENT PUBLIC BYTE ;AC000; + EXTRN EXEC_WAIT:NEAR +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN BATCH:WORD + EXTRN CALL_BATCH_FLAG:byte + EXTRN CALL_FLAG:BYTE + EXTRN ECHOFLAG:BYTE + EXTRN envirseg:word + EXTRN EXTCOM:BYTE + EXTRN FORFLAG:BYTE + EXTRN IFFLAG:BYTE + EXTRN next_batch:word + EXTRN nullflag:byte + EXTRN PIPEFILES:BYTE + EXTRN PIPEFLAG:BYTE + EXTRN RE_OUT_APP:BYTE + EXTRN RE_OUTSTR:BYTE + EXTRN RESTDIR:BYTE + EXTRN SINGLECOM:WORD + EXTRN VERVAL:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BadNam_Ptr:word ;AC000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN APPEND_EXEC:BYTE ;AN041; + EXTRN ARG1S:WORD + EXTRN ARG2S:WORD + EXTRN ARGTS:WORD + EXTRN BYTCNT:WORD + EXTRN COMBUF:BYTE + EXTRN COMSW:WORD + EXTRN CURDRV:BYTE + EXTRN HEADCALL:DWORD + EXTRN IDLEN:BYTE + EXTRN INTERNATVARS:BYTE + EXTRN PARM1:BYTE + EXTRN PARM2:BYTE + EXTRN RE_INSTR:BYTE + EXTRN RESSEG:WORD + EXTRN SPECDRV:BYTE + EXTRN STACK:WORD + EXTRN SWITCHAR:BYTE + EXTRN TPA:WORD + EXTRN UCOMBUF:BYTE + EXTRN USERDIR1:BYTE + IF IBM + EXTRN ROM_CALL:BYTE + EXTRN ROM_CS:WORD + EXTRN ROM_IP:WORD + 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 BYTE ;AC000; + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN $EXIT:NEAR + EXTRN DRVBAD:NEAR + EXTRN EXTERNAL:NEAR + EXTRN FNDCOM:NEAR + EXTRN FORPROC:NEAR + EXTRN PIPEPROC:NEAR + EXTRN PIPEPROCSTRT:NEAR + + PUBLIC COMMAND + PUBLIC DOCOM + PUBLIC DOCOM1 + PUBLIC NOPIPEPROC + PUBLIC TCOMMAND + + IF IBM + PUBLIC ROM_EXEC + PUBLIC ROM_SCAN + ENDIF + + ORG 0 +ZERO = $ + + ORG 100H ; Allow for 100H parameter area + +SETDRV: + MOV AH,SET_DEFAULT_DRIVE + INT int_command +; +; TCOMMAND is the recycle point in COMMAND. Nothing is known here. +; No registers (CS:IP) no flags, nothing. +; + +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 +; +; Main entry point from resident portion. +; +; If BP <> 0, then we have just loaded transient portion otherwise we are +; just beginning the processing of another command. +; + +COMMAND: + +; +; We are not always sure of the state of the world at this time. We presume +; worst case and initialize the relevant registers: segments and stack. +; + ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + CLD + MOV AX,CS + CLI + MOV SS,AX +ASSUME SS:TRANGROUP + MOV SP,OFFSET TRANGROUP:STACK + STI + MOV ES,AX + MOV DS,AX ;AN000; set DS to transient +ASSUME ES:TRANGROUP,DS:TRANGROUP ;AC000; + invoke TSYSLOADMSG ;AN000; preload messages + invoke SETSTDINOFF ;AN026; turn off critical error on STDIN + invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT + mov append_exec,0 ;AN041; set internal append state off + + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + + MOV [UCOMBUF],COMBUFLEN ; Init UCOMBUF + MOV [COMBUF],COMBUFLEN ; Init COMBUF (Autoexec doing DATE) +; +; If we have just loaded the transient, then we do NOT need to initialize the +; command buffer. ???? DO WE NEED TO RESTORE THE USERS DIRECTORY ???? I +; guess not: the only circumstances in which we reload the command processor +; is after a transient program execution. In this case, we let the current +; directory lie where it may. +; + 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 +; +; We have an unusual situation to handle. The user *may* have changed his +; directory as a result of an internal command that got aborted. Restoring it +; twice may not help us: the problem may never go away. We just attempt it +; once and give up. +; + MOV [RESTDIR],0 ; Flag users dirs OK + 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 + INVOKE PIPEDEL + +NOPCLOSE: + MOV [EXTCOM],0 ; Flag internal command + 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 + PUSH BX + MOV BX,16 + MUL BX ; DX:AX=size of TPA in bytes + POP BX + OR DX,DX ; See if over 64K + JZ SAVSIZ ; OK if not + MOV AX,-1 ; If so, limit to 65535 bytes + +SAVSIZ: +; +; AX is the number of bytes free in the buffer between the resident and the +; transient with a maximum of 64K-1. We round this down to a multiple of 512. +; + CMP AX,512 + JBE GotSize + AND AX,0FE00h ; NOT 511 = NOT 1FF + +GotSize: + 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 + INVOKE SINGLETEST + JB GETCOM + TEST [PIPEFLAG],-1 + JNZ GETCOM + TEST [FORFLAG],-1 ; G Don't print prompt in FOR + JNZ GETCOM ; G + TEST [BATCH], -1 ; G Don't print prompt if in batch + JNZ GETCOM ; G + INVOKE CRLF2 + +GETCOM: + MOV CALL_FLAG,0 ; G Reset call flags + MOV CALL_BATCH_FLAG,0 ; G + MOV AH,GET_DEFAULT_DRIVE + INT int_command + MOV [CURDRV],AL + TEST [PIPEFLAG],-1 ; Pipe has highest presedence + JZ NOPIPE + JMP PIPEPROC ; Continue the pipeline + +NOPIPE: + TEST [ECHOFLAG],1 + JZ NOPDRV ; No prompt if echo off + INVOKE SINGLETEST + JB NOPDRV + TEST [FORFLAG],-1 ; G Don't print prompt in FOR + JNZ NOPDRV ; G + TEST [BATCH], -1 ; G Don't print prompt if in batch + JNZ TESTFORBAT ; G + INVOKE PRINT_PROMPT ; Prompt the user + +NOPDRV: + 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 + MOV IFFlag,0 ; no more ifs... + TEST [BATCH],-1 ; Batch has lowest precedence + JZ ISNOBAT + + push es ;AN000; save ES + push ds ;AN000; save DS + mov ax,mult_shell_get ;AN000; check to see if SHELL has command + mov es,[batch] ;AN000; get batch segment + mov di,batfile ;AN000; get batch file name + push cs ;AN000; get local segment to DS + pop ds ;AN000; + mov dx,offset trangroup:combuf ;AN000; pass communications buffer + int 2fh ;AN000; call the shell + cmp al,shell_action ;AN000; does shell have a commmand? + pop ds ;AN000; restore DS + pop es ;AN000; restore ES + jz jdocom1 ;AN000; yes - go process command + + PUSH DS ;G + INVOKE READBAT ; Continue BATCH + POP DS ;G + mov nullflag,0 ;G reset no command flag + TEST [BATCH],-1 ;G + JNZ JDOCOM1 ;G if batch still in progress continue + MOV BX,NEXT_BATCH ;G + CMP BX,0 ;G see if there is a new batch file + JZ JDOCOM1 ;G no - go do command + MOV BATCH,BX ;G get segment of next batch file + MOV NEXT_BATCH,0 ;G reset next batch +JDOCOM1: + PUSH CS ;G + POP DS ;G + JMP SHORT DoCom1 ; echoing already done + +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 +; +; do NOT issue a trailing CRLF... +; + JMP DOCOM1 + +; +; We have a normal command. +; Printers are a bizarre quantity. Sometimes they are a stream and +; sometimes they aren't. At this point, we automatically close all spool +; files and turn on truncation mode. +; + +REGCOM: + MOV AX,(ServerCall SHL 8) + 9 + INT 21h + MOV AX,(ServerCall SHL 8) + 8 + MOV DL,1 + INT 21h + + 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 + +;--------------- + +transpace segment + extrn arg:byte ; the arg structure! +transpace ends +;--------------- + + +DOCOM: + INVOKE CRLF2 + +DOCOM1: + INVOKE PRESCAN ; Cook the input buffer + JZ NOPIPEPROC + JMP PIPEPROCSTRT ; Fire up the pipe + +nullcomj: + jmp nullcom + +NOPIPEPROC: + invoke parseline + jnc OkParse ; user error? or maybe we goofed? + +BadParse: + PUSH CS + POP DS + MOV DX,OFFSET TRANGROUP:BADNAM_ptr + INVOKE std_eprintf + JMP TCOMMAND + +OkParse: + test arg.argv[0].argflags, MASK wildcard + jnz BadParse ; ambiguous commands not allowed + cmp arg.argvcnt, 0 ; there WAS a command, wasn't there? + jz nullcomj + cmp arg.argv[0].arglen, 0 ; probably an unnecessary check... + jz nullcomj ; guarantees argv[0] at least x + + 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 + mov BX, arg.argv[0].argpointer + cmp BYTE PTR [BX+1],':' ; was a drive specified? + jne short drvgd ; no, use default of zero... + + mov DL, BYTE PTR [BX] ; pick-up drive letter + and DL, NOT 20H ; uppercase the sucker + sub DL, capital_A ; convert it to a drive number, A=0 + + CMP AL,-1 ; See what PARSE said about our drive letter. + JZ drvbadj2 ; It was invalid. + + mov DI, arg.argv[0].argstartel + cmp BYTE PTR [DI], 0 ; is there actually a command there? + jnz drvgd ; if not, we have: "d:", "d:\", "d:/" + jmp setdrv ; and set drive to new drive spec + +drvbadj2: + jmp drvbad + +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,8 + SUB AL,CL + MOV [IDLEN],AL ; IDLEN is truly the length + MOV DI,81H + PUSH SI + + mov si, OFFSET TRANGROUP:COMBUF+2 ; Skip over all leading delims + invoke scanoff + +do_skipcom: + lodsb ; move command line pointer over + invoke delim ; pathname -- have to do it ourselves + jz do_skipped ; 'cause parse_file_descriptor is dumb + cmp AL, 0DH ; can't always depend on argv[0].arglen + jz do_skipped ; to be the same length as the user- + cmp AL, [SWITCHAR] ; specified command string + jnz do_skipcom + +do_skipped: + dec SI + XOR CX,CX + +COMTAIL: + LODSB + STOSB ; Move command tail to 80H + CMP AL,13 + LOOPNZ COMTAIL + DEC DI + MOV BP,DI + NOT CL + MOV BYTE PTR DS:[80H],CL + POP SI + +;----- +; Some of these comments are sadly at odds with this brave new code. +;----- +; If the command has 0 parameters must check here for +; any switches that might be present. +; SI -> first character after the command. + + mov DI, arg.argv[0].argsw_word + mov [COMSW], DI ; ah yes, the old addressing mode problem... + mov SI, arg.argv[1 * SIZE argv_ele].argpointer ; s = argv[1]; + OR SI,SI ; if (s == NULL) + JNZ DoParse + MOV SI,BP ; s = bp; (buffer end) + +DoParse: + MOV DI,FCB + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H + INT int_command + MOV [PARM1],AL ; Save result of parse + + mov DI, arg.argv[1*SIZE argv_ele].argsw_word + mov [ARG1S], DI + mov SI, arg.argv[2*SIZE argv_ele].argpointer ; s = argv[2]; + OR SI,SI ; if (s == NULL) + JNZ DoParse2 + MOV SI,BP ; s = bp; (bufend)1 + +DoParse2: + MOV DI,FCB+10H + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H + INT int_command ; Parse file name + MOV [PARM2],AL ; Save result + + mov DI, arg.argv[2*SIZE argv_ele].argsw_word + mov [ARG2S], DI + mov DI, arg.argv[0].argsw_word + not DI ; ARGTS doesn't include the flags + and DI, arg.argswinfo ; from COMSW... + mov [ARGTS], DI + + MOV AL,[IDLEN] + MOV DL,[SPECDRV] + or DL, DL ; if a drive was specified... + jnz externalj1 ; it MUST be external, by this time + dec al ; (I don't know why -- old code did it) + jmp fndcom ; otherwise, check internal com table + +externalj1: + jmp external + +nullcom: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + TEST [BATCH], -1 ;G Are we in a batch file? + JZ nosetflag ;G only set flag if in batch + mov nullflag,nullcommand ;G set flag to indicate no command + +nosetflag: + CMP [SINGLECOM],-1 + JZ EXITJ + JMP GETCOM + +EXITJ: + JMP $EXITPREP + +IF IBM + include mshalo.asm +ENDIF + +TRANCODE ENDS + END -- cgit v1.2.3