2 ; SCCSID = @(#)command2.asm 4.3 85/10/16
3 ; SCCSID = @(#)command2.asm 4.3 85/10/16
4 TITLE COMMAND2
- resident
code for COMMAND
.COM part II
11 INCLUDE resmsg
.equ
;AN000;
17 CODERES
SEGMENT PUBLIC BYTE ;AC000;
20 DATARES
SEGMENT PUBLIC BYTE
21 EXTRN append_state
:word ;AN020;
22 EXTRN append_flag
:byte ;AN020;
24 EXTRN comprmt1_block
:byte ;AN000;
25 EXTRN comprmt1_subst
:byte ;AN000;
32 EXTRN INT_2E_RET
:DWORD ;AC000;
37 EXTRN number_subst
:byte ;AN000;
38 EXTRN OldTerm
:DWORD ;AC000;
39 EXTRN PARENT
:WORD ;AC000;
44 EXTRN rsrc_xa_seg
:word ;AN030;
56 BATARENA
SEGMENT PUBLIC PARA
;AC000;
59 BATSEG
SEGMENT PUBLIC PARA
;AC000;
62 ENVARENA
SEGMENT PUBLIC PARA
;AC000;
65 ENVIRONMENT
SEGMENT PUBLIC PARA
; Default COMMAND environment
68 INIT
SEGMENT PUBLIC PARA
75 TAIL
SEGMENT PUBLIC PARA
78 TRANCODE
SEGMENT PUBLIC PARA
81 TRANDATA
SEGMENT PUBLIC BYTE
82 EXTRN TRANDATAEND
:BYTE
85 TRANSPACE
SEGMENT PUBLIC BYTE
86 EXTRN TRANSPACEEND
:BYTE
90 TRANTAIL
SEGMENT PUBLIC PARA
93 RESGROUP GROUP CODERES
,DATARES
,BATARENA
,BATSEG
,ENVARENA
,ENVIRONMENT
,INIT
,TAIL
94 TRANGROUP GROUP TRANCODE
,TRANDATA
,TRANSPACE
,TRANTAIL
96 ; START OF RESIDENT PORTION
98 CODERES
SEGMENT PUBLIC BYTE ;AC000;
114 ASSUME
CS:RESGROUP
,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
120 ; If we cannot allocate enough memory for the transient or there was some
121 ; other allocation error, we display a message and then die.
123 BADMEMERR: ; Allocation error loading transient
124 MOV DX,BMEMMES
;AC000; get message number
131 ; If this is NOT a permanent (top-level) COMMAND, then we exit; we can't do
137 ; We are a permanent command. If we are in the process of the magic interrupt
138 ; (Singlecom) then exit too.
140 CMP SINGLECOM
,0 ; If PERMCOM and SINGLECOM
141 JNZ FATALRET
; Must take INT_2E exit
143 ; Permanent command. We can't do ANYthing except halt.
145 MOV DX,HALTMES
;AC000; get message number
149 JMP STALL
; Crash the system nicely
152 MOV DX,FRETMES
;AC000; get message number
155 CMP [PERMCOM
],0 ; If we get here and PERMCOM,
156 JNZ RET_2E
; must be INT_2E
157 invoke reset_msg_pointers
;AN000; reset critical & parse error messages
159 MOV WORD PTR CS:[PDB_Parent_PID
],AX
160 MOV AX,WORD PTR OldTerm
161 MOV WORD PTR CS:[PDB_Exit
],AX
162 MOV AX,WORD PTR OldTerm
+2
163 MOV WORD PTR CS:[PDB_Exit
+2],AX
164 MOV AX,(EXIT
SHL 8) ; Return to lower level
170 ASSUME
DS:RESGROUP
,ES:NOTHING
,SS:NOTHING
171 MOV [SINGLECOM
],0 ; Turn off singlecom
174 INT int_command
; Free up space used by transient
176 MOV AH,SET_CURRENT_PDB
177 INT int_command
; Current process is user
181 XOR AX,AX ; Internals always return 0
183 MOV [EXTCOM
],1 ; Force external
184 JMP [INT_2E_RET
] ;"IRET"
186 INT_2E: ; Magic command executer
187 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
188 POP WORD PTR [INT_2E_RET
]
189 POP WORD PTR [INT_2E_RET
+2] ;Get return address
196 MOV AH,GET_CURRENT_PDB
197 INT int_command
; Get user's header
199 MOV AH,SET_CURRENT_PDB
201 INT int_command
; Current process is me
203 MOV [EXTCOM
],1 ; Make sure this case forced
205 LODCOM: ; Termination handler
207 jz lodcom1
; if internal, memory already allocated
213 CMP BX,AX ; Is less than 512 byte buffer worth it?
216 JMP BADMEMERR
; Not enough memory
218 ; SetSize - get transient size in paragraphs
219 Procedure SetSize
,NEAR
220 MOV AX,OFFSET TRANGROUP
:TRANSPACEEND
+ 15
229 JC BADMEMERRJ
; Memory arenas probably trashed
230 MOV [EXTCOM
],0 ; Flag not to ALLOC again
231 MOV [RES_TPA
], AX ; Save current TPA segment
233 ADD AX, 01000H ; Round up to next 64K boundary
234 JC BAD_TPA
; Memory wrap if carry set
235 ; Make sure that new boundary is within allocated range
237 ADD DX, BX ; Compute maximum address
238 CMP DX, AX ; Is 64K address out of range?
240 ; Must have 64K of usable space.
241 SUB DX, AX ; Compute the usable space
242 CMP DX, 01000H ; Is space >= 64K ?
247 MOV [LTPA
],AX ; Usable TPA is 64k buffer aligned
248 MOV AX, [RES_TPA
] ; Actual TPA is buffer allocated
253 MOV [TRNSEG
],BX ; Transient starts here
258 MOV SP,OFFSET RESGROUP
:RSTACK
261 CALL HEADFIX
; Make sure files closed stdin and stdout restored
262 XOR BP,BP ; Flag command ok
267 MOV AH,SET_VERIFY_ON_WRITE
; AL has correct value
272 JMP FATALRET2
; We have finished the single command
274 CALL CHKSUM
; Check the transient
276 JZ HAVCOM
; Transient OK
278 MOV [LOADING
],1 ; Flag DSKERR routine
284 JZ HAVCOM
; Same COMMAND
289 MOV AX,CHAR_OPER
SHL 8
295 MOV [RDIRCHAR],cl ; Select alt path separator
297 MOV [LOADING],0 ; Flag to DSKERR
298 MOV SI,OFFSET RESGROUP:TRANVARS
299 MOV DI,OFFSET TRANGROUP:HEADCALL
302 MOV CX,OFFSET ResGroup:TranVarEnd
304 REP MOVSB ; Transfer INFO to transient
306 MOV WORD PTR DS:[PDB_block_len],AX ; Adjust my own header
308 ; Just a public label so this spot can be found easily.
310 JMP DWORD PTR [TRANS]
312 ; Far call to REMCHECK for TRANSIENT
319 ;All registers preserved. Returns ZF set if media removable, NZ if fixed
320 ; AL is drive (0=DEF, 1=A,...).
323 MOV AX,(IOCTL SHL 8) + 8
325 jnc RCcont ; If an error occurred, assume the media
326 or ax,ax ; is NON-removable.
327 ; AX contains the non-zero error code
328 ; from the INT 21, so the OR AX,AX sets
329 ; Non-zero. This behavior makes Network
330 ; drives appear to be non-removable.
339 ; Far call to HEADFIX for TRANSIENT
347 XOR BX,BX ; Clean up header
349 MOV DX,WORD PTR DS:[PDB_JFN_Table]
351 JZ CHK1 ; Stdin matches
354 MOV DS:[PDB_JFN_Table],CL ; Restore stdin
357 CMP CH,DH ; Stdout matches
361 MOV DS:[PDB_JFN_Table+1],CH ; Restore stdout
363 ADD BX,4 ; Skip 2,3,4
364 MOV CX,FilPerProc - 5 ; Already done 0,1,2,3,4
370 push ds ;AN020; save data segment
371 push cs ;AN020; Get local segment into DS
373 cmp append_flag,-1 ;AN020; Do we need to reset APPEND?
374 jnz append_fix_end ;AN030; no - just exit
375 mov ax,AppendSetState ;AN020; Set the state of Append
376 mov bx,Append_state ;AN020; back to the original state
378 mov append_flag,0 ;AN020; Set append flag to invalid
379 append_fix_end: ;AN030;
380 cmp [rsrc_xa_seg],no_xa_seg ;AN030; Is there any active XA segment?
381 jz xa_fix_end ;AN030; no - exit
382 push es ;AN030; Yes - deallocate it
383 mov es,rsrc_xa_seg ;AN030;
384 mov ax,(Dealloc SHL 8) ;AN030; Deallocate memory call
385 int int_command ;AN030;
387 mov [rsrc_xa_seg],no_xa_seg ;AN030; reset to no segment
389 pop ds ;AN020; get data segment back
393 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
395 PUSH BX ; Set stdin to sterr, stdout to stderr
397 MOV AH,GET_CURRENT_PDB
398 INT int_command ; Get user's header
400 LDS BX,DS:[PDB_JFN_POINTER] ; get pointer to JFN table...
401 MOV AX,WORD PTR DS:[BX]
402 MOV [HANDLE01],AX ; Save user's stdin, stdout
403 MOV AL,CS:[PDB_JFN_Table+2] ; get COMMAND stderr
405 MOV WORD PTR DS:[BX],AX ; Dup stderr
414 JMP LODCOM1 ; Memory already allocated
418 PUSH BX ; Restore stdin, stdout to user
420 MOV AH,GET_CURRENT_PDB
421 INT int_command ; Point to user's header
425 LDS BX,DS:[PDB_JFN_POINTER] ; get pointer to JFN table...
426 MOV WORD PTR DS:[BX],AX ; Stuff his old 0 and 1
431 ASSUME DS:RESGROUP,SS:RESGROUP
434 MOV DX,COMBAD ;AC000;
440 jNZ HOPELESS ;Non-removable media
442 cmp dx,combad ;AC000;
444 mov dx,combad ;AN000; get message number
445 invoke RPRINT ; Say command is invalid
447 cmp [cpdrv],0 ;g is there a drive in the comspec?
448 jnz users_drive ;g yes - use it
449 mov ah,Get_default_drive ;g use default drive
451 add al,"A" ;g convert to ascii
452 mov [cpdrv],al ;g put in message to print out
455 mov dx,comprmt1 ;AC000; Prompt for diskette containing command
459 MOV AL,COMPRMT1_SUBST ;AN000; get number of substitutions
460 MOV SI,OFFSET RESGROUP:COMPRMT1_BLOCK ;AN000; get address of subst block
461 MOV NUMBER_SUBST,AL ;AN000;
464 and byte ptr [si],NOT 80h
466 mov dx,prompt ;AN047; Tell the user to strike a key
467 invoke rprint ;AN047;
468 CALL GetRawFlushedByte
471 ; flush world and get raw input
473 MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR RAW_CON_INPUT
474 INT int_command ; Get char without testing or echo
475 MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0
479 LOADCOM: ; Load in transient
480 INC BP ; Flag command read
481 MOV DX,OFFSET RESGROUP:COMSPEC
483 INT int_command ; Open COMMAND.COM
485 CMP AX,error_too_many_open_files
487 MOV DX,NOHANDMES ;AC000;
488 JMP FATALC ; Fatal, will never find a handle
496 MOV DX,OFFSET RESGROUP:TRANSTART
501 MOV CX,OFFSET TRANGROUP:TRANSPACEEND - 100H
515 INT int_command ; Close COMMAND.COM
518 JC WRONGCOM ; If error on READ
522 MOV DX,COMBAD ;AC000;
524 JMP LOADCOM ; Try again
526 CHKSUM: ; Compute transient checksum
530 MOV CX,OFFSET TRANGROUP:TranDataEnd - 100H
544 SETVECT: ; Set useful vectors
545 MOV DX,OFFSET RESGROUP:LODCOM
546 MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 22H
547 MOV WORD PTR DS:[PDB_EXIT],DX
548 MOV WORD PTR DS:[PDB_EXIT+2],DS
550 MOV DX,OFFSET RESGROUP:CONTC
553 MOV DX,OFFSET RESGROUP:DSKERR
560 ; This routine moves the environment to a newly allocated segment
561 ; at the end of initialization
565 push ds ;g save segments
567 push cs ;g get resident segment to DS
570 mov cx,usedenv ;g get number of bytes to move
571 mov es,envirseg ;g get target environment segment
574 mov DS:[PDB_environ],es ;g put new environment in my header ;AM067;
575 mov ds,oldenv ;g source environment segment ;AM067;
576 ASSUME DS:NOTHING ;AM067;
577 xor si,si ;g set up offsets to start of segments ;AM067;
579 cld ;g make sure we move the right way! ;AM067;
580 rep movsb ;g move it ;AM067;
582 stosb ;g make sure there are double 0 at end ;AM067;
584 cmp resetenv,1 ;eg Do we need to setblock to env end?
585 jnz noreset ;eg no - we already did it
586 mov bx,envsiz ;eg get size of environment in paragraphs
587 push es ;eg save environment - just to make sure
593 mov InitFlag,FALSE ;AC042; Turn off init flag
596 jmp lodcom ;g allocate transient
600 ; This TAIL segment is used to produce a PARA aligned label in the resident
601 ; group which is the location where the transient segments will be loaded
604 TAIL SEGMENT PUBLIC PARA
610 ; This TAIL segment is used to produce a PARA aligned label in the transient
611 ; group which is the location where the exec segments will be loaded
614 TRANTAIL SEGMENT PUBLIC PARA