2 ; SCCSID = @(#)tcode.asm 1.1 85/05/14
3 ; SCCSID = @(#)tcode.asm 1.1 85/05/14
4 TITLE Part1 COMMAND Transient Routines
16 CODERES
SEGMENT PUBLIC BYTE ;AC000;
20 DATARES
SEGMENT PUBLIC BYTE ;AC000;
22 EXTRN CALL_BATCH_FLAG
:byte
40 TRANDATA
SEGMENT PUBLIC BYTE ;AC000;
41 EXTRN BadNam_Ptr
:word ;AC000;
44 TRANSPACE
SEGMENT PUBLIC BYTE ;AC000;
45 EXTRN APPEND_EXEC
:BYTE ;AN041;
55 EXTRN INTERNATVARS
:BYTE
74 ; ********************************************************************
75 ; START OF TRANSIENT PORTION
76 ; This code is loaded at the end of memory and may be overwritten by
77 ; memory-intensive user programs.
79 TRANCODE
SEGMENT PUBLIC BYTE ;AC000;
81 ASSUME
CS:TRANGROUP
,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
89 EXTRN PIPEPROCSTRT
:NEAR
105 ORG 100H
; Allow for 100H parameter area
108 MOV AH,SET_DEFAULT_DRIVE
111 ; TCOMMAND is the recycle point in COMMAND. Nothing is known here.
112 ; No registers (CS:IP) no flags, nothing.
122 MOV AH,SET_VERIFY_ON_WRITE
; AL has correct value
126 CALL [HEADCALL
] ; Make sure header fixed
127 XOR BP,BP ; Flag transient not read
134 JMP $EXIT
; Have finished the single command
137 ; Main entry point from resident portion.
139 ; If BP <> 0, then we have just loaded transient portion otherwise we are
140 ; just beginning the processing of another command.
146 ; We are not always sure of the state of the world at this time. We presume
147 ; worst case and initialize the relevant registers: segments and stack.
149 ASSUME
CS:TRANGROUP
,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
155 MOV SP,OFFSET TRANGROUP
:STACK
158 MOV DS,AX ;AN000; set DS to transient
159 ASSUME
ES:TRANGROUP
,DS:TRANGROUP
;AC000;
160 invoke TSYSLOADMSG
;AN000; preload messages
161 invoke SETSTDINOFF
;AN026; turn off critical error on STDIN
162 invoke SETSTDOUTOFF
;AN026; turn off critical error on STDOUT
163 mov append_exec
,0 ;AN041; set internal append state off
168 MOV [UCOMBUF
],COMBUFLEN
; Init UCOMBUF
169 MOV [COMBUF
],COMBUFLEN
; Init COMBUF (Autoexec doing DATE)
171 ; If we have just loaded the transient, then we do NOT need to initialize the
172 ; command buffer. ???? DO WE NEED TO RESTORE THE USERS DIRECTORY ???? I
173 ; guess not: the only circumstances in which we reload the command processor
174 ; is after a transient program execution. In this case, we let the current
175 ; directory lie where it may.
177 OR BP,BP ; See if just read
178 JZ TESTRDIR
; Not read, check user directory
179 MOV WORD PTR [UCOMBUF
+1],0D01H ; Reset buffer
184 JZ NOSETBUF
; User directory OK
187 ; We have an unusual situation to handle. The user *may* have changed his
188 ; directory as a result of an internal command that got aborted. Restoring it
189 ; twice may not help us: the problem may never go away. We just attempt it
192 MOV [RESTDIR
],0 ; Flag users dirs OK
196 MOV DX,OFFSET TRANGROUP
:USERDIR1
198 INT int_command
; Restore users directory
204 JZ NOPCLOSE
; Don't bother if they don't exist
206 JNZ NOPCLOSE
; Don't del if still piping
210 MOV [EXTCOM
],0 ; Flag internal command
211 MOV AX,CS ; Get segment we're in
216 MOV DX,OFFSET TRANGROUP
:INTERNATVARS
217 MOV AX,INTERNATIONAL
SHL 8
220 SUB AX,[TPA
] ; AX=size of TPA in paragraphs
223 MUL BX ; DX:AX=size of TPA in bytes
225 OR DX,DX ; See if over 64K
226 JZ SAVSIZ
; OK if not
227 MOV AX,-1 ; If so, limit to 65535 bytes
231 ; AX is the number of bytes free in the buffer between the resident and the
232 ; transient with a maximum of 64K-1. We round this down to a multiple of 512.
236 AND AX,0FE00h ; NOT 511 = NOT 1FF
239 MOV [BYTCNT
],AX ; Max no. of bytes that can be buffered
240 MOV DS,[RESSEG
] ; All batch work must use resident seg.
244 JZ GETCOM
; Don't do the CRLF
249 TEST [FORFLAG
],-1 ; G Don't print prompt in FOR
251 TEST [BATCH
], -1 ; G Don't print prompt if in batch
256 MOV CALL_FLAG
,0 ; G Reset call flags
257 MOV CALL_BATCH_FLAG
,0 ; G
258 MOV AH,GET_DEFAULT_DRIVE
261 TEST [PIPEFLAG
],-1 ; Pipe has highest presedence
263 JMP PIPEPROC
; Continue the pipeline
267 JZ NOPDRV
; No prompt if echo off
270 TEST [FORFLAG
],-1 ; G Don't print prompt in FOR
272 TEST [BATCH
], -1 ; G Don't print prompt if in batch
274 INVOKE PRINT_PROMPT
; Prompt the user
277 TEST [FORFLAG
],-1 ; FOR has next highest precedence
279 JMP FORPROC
; Continue the FOR
282 MOV [RE_INSTR
],0 ; Turn redirection back off
285 MOV IFFlag
,0 ; no more ifs...
286 TEST [BATCH
],-1 ; Batch has lowest precedence
289 push es ;AN000; save ES
290 push ds ;AN000; save DS
291 mov ax,mult_shell_get
;AN000; check to see if SHELL has command
292 mov es,[batch
] ;AN000; get batch segment
293 mov di,batfile
;AN000; get batch file name
294 push cs ;AN000; get local segment to DS
296 mov dx,offset trangroup
:combuf
;AN000; pass communications buffer
297 int 2fh
;AN000; call the shell
298 cmp al,shell_action
;AN000; does shell have a commmand?
299 pop ds ;AN000; restore DS
300 pop es ;AN000; restore ES
301 jz jdocom1
;AN000; yes - go process command
304 INVOKE READBAT
; Continue BATCH
306 mov nullflag
,0 ;G reset no command flag
308 JNZ JDOCOM1
;G if batch still in progress continue
310 CMP BX,0 ;G see if there is a new batch file
311 JZ JDOCOM1
;G no - go do command
312 MOV BATCH
,BX ;G get segment of next batch file
313 MOV NEXT_BATCH
,0 ;G reset next batch
317 JMP SHORT DoCom1
; echoing already done
324 MOV DI,OFFSET TRANGROUP
:COMBUF
+ 2
339 ; do NOT issue a trailing CRLF...
344 ; We have a normal command.
345 ; Printers are a bizarre quantity. Sometimes they are a stream and
346 ; sometimes they aren't. At this point, we automatically close all spool
347 ; files and turn on truncation mode.
351 MOV AX,(ServerCall
SHL 8) + 9
353 MOV AX,(ServerCall
SHL 8) + 8
358 POP DS ; Need local segment to point to buffer
359 MOV DX,OFFSET TRANGROUP
:UCOMBUF
360 MOV AH,STD_CON_STRING_INPUT
361 INT int_command
; Get a command
365 MOV SI,OFFSET TRANGROUP
:UCOMBUF
366 MOV DI,OFFSET TRANGROUP
:COMBUF
367 REP MOVSB ; Transfer it to the cooked buffer
372 extrn arg
:byte ; the arg structure!
381 INVOKE PRESCAN
; Cook the input buffer
383 JMP PIPEPROCSTRT
; Fire up the pipe
390 jnc OkParse
; user error? or maybe we goofed?
395 MOV DX,OFFSET TRANGROUP
:BADNAM_ptr
400 test arg
.argv
[0].argflags
, MASK wildcard
401 jnz BadParse
; ambiguous commands not allowed
402 cmp arg
.argvcnt
, 0 ; there WAS a command, wasn't there?
404 cmp arg
.argv
[0].arglen
, 0 ; probably an unnecessary check...
405 jz nullcomj
; guarantees argv[0] at least x<NULL>
407 MOV SI,OFFSET TRANGROUP
:COMBUF
+2
408 MOV DI,OFFSET TRANGROUP
:IDLEN
409 MOV AX,(PARSE_FILE_DESCRIPTOR
SHL 8) OR 01H ; Make FCB with blank scan-off
411 mov BX, arg
.argv
[0].argpointer
412 cmp BYTE PTR [BX+1],':' ; was a drive specified?
413 jne short drvgd
; no, use default of zero...
415 mov DL, BYTE PTR [BX] ; pick-up drive letter
416 and DL, NOT 20H
; uppercase the sucker
417 sub DL, capital_A
; convert it to a drive number, A=0
419 CMP AL,-1 ; See what PARSE said about our drive letter.
420 JZ drvbadj2
; It was invalid.
422 mov DI, arg
.argv
[0].argstartel
423 cmp BYTE PTR [DI], 0 ; is there actually a command there?
424 jnz drvgd
; if not, we have: "d:", "d:\", "d:/"
425 jmp setdrv
; and set drive to new drive spec
436 REPNE SCASB ; Count no. of letters in command name
439 MOV [IDLEN
],AL ; IDLEN is truly the length
443 mov si, OFFSET TRANGROUP
:COMBUF
+2 ; Skip over all leading delims
447 lodsb ; move command line pointer over
448 invoke delim
; pathname -- have to do it ourselves
449 jz do_skipped
; 'cause parse_file_descriptor is dumb
450 cmp AL, 0DH ; can't always depend on argv[0].arglen
451 jz do_skipped
; to be the same length as the user-
452 cmp AL, [SWITCHAR
] ; specified command string
461 STOSB ; Move command tail to 80H
467 MOV BYTE PTR DS:[80H
],CL
471 ; Some of these comments are sadly at odds with this brave new code.
473 ; If the command has 0 parameters must check here for
474 ; any switches that might be present.
475 ; SI -> first character after the command.
477 mov DI, arg
.argv
[0].argsw_word
478 mov [COMSW
], DI ; ah yes, the old addressing mode problem...
479 mov SI, arg
.argv
[1 * SIZE argv_ele
].argpointer
; s = argv[1];
480 OR SI,SI ; if (s == NULL)
482 MOV SI,BP ; s = bp; (buffer end)
486 MOV AX,(PARSE_FILE_DESCRIPTOR
SHL 8) OR 01H
488 MOV [PARM1
],AL ; Save result of parse
490 mov DI, arg
.argv
[1*SIZE argv_ele
].argsw_word
492 mov SI, arg
.argv
[2*SIZE argv_ele
].argpointer
; s = argv[2];
493 OR SI,SI ; if (s == NULL)
495 MOV SI,BP ; s = bp; (bufend)1
499 MOV AX,(PARSE_FILE_DESCRIPTOR
SHL 8) OR 01H
500 INT int_command
; Parse file name
501 MOV [PARM2
],AL ; Save result
503 mov DI, arg
.argv
[2*SIZE argv_ele
].argsw_word
505 mov DI, arg
.argv
[0].argsw_word
506 not DI ; ARGTS doesn't include the flags
507 and DI, arg
.argswinfo
; from COMSW...
512 or DL, DL ; if a drive was specified...
513 jnz externalj1
; it MUST be external, by this time
514 dec al ; (I don't know why -- old code did it)
515 jmp fndcom
; otherwise, check internal com table
523 TEST [BATCH
], -1 ;G Are we in a batch file?
524 JZ nosetflag
;G only set flag if in batch
525 mov nullflag
,nullcommand
;G set flag to indicate no command