]>
wirehaze git hosting - MS-DOS.git/blob - v2.0/source/COMMAND.ASM
2 ; This version of COMMAND is divided into three distinct parts. First is the
3 ; resident portion, which includes handlers for interrupts 22H (terminate),
4 ; 23H (Cntrl-C), 24H (fatal error), and 27H (stay resident); it also has code
5 ; to test and, if necessary, reload the transient portion. Following the
6 ; resident is the init code, which is overwritten after use. Then comes the
7 ; transient portion, which includes all command processing (whether internal
8 ; or external). The transient portion loads at the end of physical memory,
9 ; and it may be overlayed by programs that need as much memory as possible.
10 ; When the resident portion of command regains control from a user program, a
11 ; checksum is performed on the transient portion to see if it must be
12 ; reloaded. Thus programs which do not need maximum memory will save the time
13 ; required to reload COMMAND when they terminate.
17 ; 05/19/82 Fixed bug in BADEXE error (relocation error must return to
18 ; resident since the EXELOAD may have overwritten the transient.
20 ; 05/21/82 IBM version always looks on drive A
21 ; MSVER always looks on default drive
24 ; 06/03/82 Drive spec now entered in command line
25 ; 06/07/82 Added VER command (print DOS version number) and VOL command
26 ; (print volume label)
28 ; 06/09/82 Prints "directory" after directories
29 ; 06/13/82 MKDIR, CHDIR, PWD, RMDIR added
31 ; Some code for new 2.0 DOS, sort of HACKey. Not enough time to
34 ; EXEC used to fork off new processes
36 ; C switch for single command execution
43 ; 'D' switch for date time suppression
45 ; Default userpath is NUL rather than BIN
47 ; COMMAND split into pieces
49 ; INTERNATIONAL SUPPORT
50 ; Rev 2.11 COMMAND split into more pieces
57 CODERES
SEGMENT PUBLIC
60 DATARES
SEGMENT PUBLIC BYTE
61 EXTRN COMBAD
:BYTE,NEEDCOM
:BYTE,DRVMSG
:BYTE
62 EXTRN DEFMSG
:BYTE,PROMPT
:BYTE,EXECEMES
:BYTE,EXEBAD
:BYTE
63 EXTRN TOOBIG
:BYTE,NOCOM
:BYTE,RBADNAM
:BYTE,INT_2E_RET
:DWORD
64 EXTRN NOHANDMES
:BYTE,BMEMMES
:BYTE,HALTMES
:BYTE,FRETMES
:BYTE
65 EXTRN PARENT
:WORD,HANDLE01
:WORD,LOADING
:BYTE,BATCH
:WORD
66 EXTRN TRNSEG
:WORD,COMDRV
:BYTE,MEMSIZ
:WORD,SUM
:WORD,EXTCOM
:BYTE
67 EXTRN IO_SAVE
:WORD,PERMCOM
:BYTE,SINGLECOM
:WORD,VERVAL
:WORD
68 EXTRN PIPEFLAG
:BYTE,SAVE_PDB
:WORD,COMSPEC
:BYTE,TRANS
:WORD
69 EXTRN TRANVARS
:BYTE,LTPA
:WORD,RSWITCHAR
:BYTE,RDIRCHAR
:BYTE
70 EXTRN RETCODE
:WORD,FORFLAG
:BYTE
73 EXTRN SYS_CALL
:DWORD,ZEXEC
:WORD,EXESEG
:WORD,EXESUM
:WORD
74 EXTRN USER_SS
:WORD,USER_SP
:WORD
79 ENVIRONMENT
SEGMENT PUBLIC PARA
; Default COMMAND environment
82 INIT
SEGMENT PUBLIC PARA
86 TAIL
SEGMENT PUBLIC PARA
89 TRANCODE
SEGMENT PUBLIC PARA
92 TRANDATA
SEGMENT PUBLIC BYTE
93 EXTRN TRANDATAEND
:BYTE
96 TRANSPACE
SEGMENT PUBLIC BYTE
97 EXTRN TRANSPACEEND
:BYTE,HEADCALL
:DWORD
100 TRANTAIL
SEGMENT PUBLIC PARA
103 ZEXEC_CODE
SEGMENT PUBLIC PARA
106 ZEXEC_DATA
SEGMENT PUBLIC BYTE
109 RESGROUP GROUP CODERES
,DATARES
,ENVIRONMENT
,INIT
,TAIL
110 TRANGROUP GROUP TRANCODE
,TRANDATA
,TRANSPACE
,TRANTAIL
111 EGROUP GROUP ZEXEC_CODE
,ZEXEC_DATA
113 ENVIRONMENT
SEGMENT PUBLIC PARA
; Default COMMAND environment
115 PUBLIC ECOMSPEC
,ENVIREND
,PATHSTRING
118 ENVARENA
DB 10H
DUP (?
) ; Pad for mem arena
119 PATHSTRING
DB "PATH="
124 ECOMSPEC
DB "/COMMAND.COM"
129 ENVIRONSIZ EQU
$-PATHSTRING
130 ENVIRONSIZ2 EQU
$-ECOMSPEC
134 ; START OF RESIDENT PORTION
136 CODERES
SEGMENT PUBLIC
138 PUBLIC GETCOMDSK2
,LODCOM
,THEADFIX
,CONTCTERM
,LOADCOM
,INT_2E
,LODCOM1
139 PUBLIC CHKSUM
,SETVECT
,EXT_EXEC
,TREMCHECK
,RESTHAND
,CONTC
,RSTACK
143 PUBLIC EXECHK
,SYSCALL,EXEC_WAIT
146 ASSUME
CS:RESGROUP
,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
148 EXTRN RPRINT
:NEAR,ASKEND
:NEAR,DSKERR
:NEAR
166 JMP DWORD PTR [SYS_CALL
]
181 ; are we running on RSTACK already?
187 CMP AX,BX ; IF AX == BX then no stack switch!
191 MOV SP,OFFSET RESGROUP
:RSTACK
194 MOV BX,0FFFFH ; allocate all of memory
197 MOV AX,OFFSET EGROUP
:ZEXECDATAEND
+ 15
200 MOV CX,AX ; Save in CX
201 CMP BX,AX ; enough for EXEC?
202 JB EXECMER
; nope... cry
205 JC EXECMER
; Memory arenas probably trashed
209 MOV [EXESEG
],BX ; exec
219 MOV DX,OFFSET RESGROUP
:COMSPEC
221 INT int_command
; Open COMMAND.COM
224 MOV DX,OFFSET RESGROUP
:TRANSTART
225 ADD DX,OFFSET TRANGROUP
:EXECSTART
- 100H
229 MOV CX,OFFSET EGROUP
:ZEXECCODEEND
236 INT int_command
; Close COMMAND.COM
238 CMP CX,OFFSET EGROUP
:ZEXECCODEEND
239 JNZ EXECMER
; Size matched
245 MOV [LOADING
],0 ; Flag to DSKERR
246 CALL DWORD PTR [ZEXEC
]
249 LDS SI,DWORD PTR [user_Sp
]
250 MOV [SI.user_AX
],exec_not_enough_memory
272 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
275 MOV CX,OFFSET EGROUP
:ZEXECCODEEND
280 EXEC_ERR: ; Select the correct error message
281 MOV DX,OFFSET RESGROUP
:RBADNAM
282 CMP AX,exec_file_not_found
284 CMP AX,error_access_denied
286 MOV DX,OFFSET RESGROUP
:TOOBIG
287 CMP AX,exec_not_enough_memory
289 MOV DX,OFFSET RESGROUP
:EXEBAD
290 CMP AX,exec_bad_format
292 MOV DX,OFFSET RESGROUP
:EXECEMES
301 ; we are now running in free space. anything we do from here
302 ; on may get trashed. Move the stack (also in free space) to
303 ; allocated space because since EXEC restores the stack,
304 ; somebody may trash what is on the stack.
308 MOV SP,OFFSET RESGROUP
:RSTACK
310 ; Oops!! We have to make sure that the EXEC code doesn't blop a newstack!
313 INT int_command
; Do the EXEC
314 JC EXEC_ERR
; EXEC failed
317 INT int_command
; Get the return code
328 INT int_command
; Reset disks in case files were open
331 JMP ASKEND
; See if user wants to terminate batch
333 XOR BP,BP ; Indicate no read
334 MOV [FORFLAG
],0 ; Turn off for processing
335 MOV [PIPEFLAG
],0 ; Turn off any pipe
336 CMP [SINGLECOM
],0 ; See if we need to set SINGLECOM
338 MOV [SINGLECOM
],-1 ; Cause termination on pipe, batch, for
341 JNZ DODAB
; Internal ^C
344 STC ; Tell DOS to abort
346 RET ; Leave flags on stack
349 BADMEMERR: ; Allocation error loading transient
350 MOV DX,OFFSET RESGROUP
:BMEMMES
357 CMP [SINGLECOM
],0 ; If PERMCOM and SINGLECOM
358 JNZ FATALRET
; Must take INT_2E exit
359 MOV DX,OFFSET RESGROUP
:HALTMES
362 JMP STALL
; Crash the system nicely
365 MOV DX,OFFSET RESGROUP
:FRETMES
368 CMP [PERMCOM
],0 ; If we get here and PERMCOM,
369 JNZ RET_2E
; must be INT_2E
371 LDS DX,DWORD PTR [SYS_CALL
]
373 MOV AX,(SET_INTERRUPT_VECTOR
SHL 8) + INT_COMMAND
377 MOV WORD PTR CS:[PDB_Parent_PID
],AX
378 MOV AX,(EXIT
SHL 8) ; Return to lower level
384 ASSUME
DS:RESGROUP
,ES:NOTHING
,SS:NOTHING
385 MOV [SINGLECOM
],0 ; Turn off singlecom
388 INT int_command
; Free up space used by transient
390 MOV AH,SET_CURRENT_PDB
391 INT int_command
; Current process is user
395 XOR AX,AX ; Internals always return 0
397 MOV [EXTCOM
],1 ; Force external
398 JMP [INT_2E_RET
] ;"IRET"
400 INT_2E: ; Magic command executer
401 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
402 POP WORD PTR [INT_2E_RET
]
403 POP WORD PTR [INT_2E_RET
+2] ;Get return address
410 MOV AH,GET_CURRENT_PDB
411 INT int_command
; Get user's header
413 MOV AH,SET_CURRENT_PDB
415 INT int_command
; Current process is me
417 MOV [EXTCOM
],1 ; Make sure this case forced
419 LODCOM: ; Termination handler
421 JZ LODCOM1
; If internal, memory already allocated
425 MOV AX,OFFSET TRANGROUP
:TRANSPACEEND
+ 15
431 MOV AX,OFFSET EGROUP
:ZEXECDATAEND
+ 15
439 CMP BX,AX ; Is less than 512 byte buffer worth it?
442 JMP BADMEMERR
; Not enough memory
446 JC BADMEMERRJ
; Memory arenas probably trashed
447 MOV [EXTCOM
],0 ; Flag not to ALLOC again
448 MOV [LTPA
],AX ; New TPA is base just allocated
452 MOV AX,OFFSET TRANGROUP
:TRANSPACEEND
+ 15
458 MOV AX,OFFSET EGROUP
:ZEXECDATAEND
+ 15
466 MOV [TRNSEG
],BX ; Transient starts here
471 MOV SP,OFFSET RESGROUP
:RSTACK
474 CALL HEADFIX
; Make sure files closed stdin and stdout restored
475 XOR BP,BP ; Flag command ok
480 MOV AH,SET_VERIFY_ON_WRITE
; AL has correct value
485 JMP FATALRET2
; We have finished the single command
490 CALL EXECHK
; Check exe loader
495 CALL CHKSUM
; Check the transient
497 JZ HAVCOM
; Transient OK
499 MOV [LOADING
],1 ; Flag DSKERR routine
511 JZ HAVCOM
; Same COMMAND
516 MOV AX,CHAR_OPER
SHL 8
521 MOV [RDIRCHAR
],'\' ; Select alt path separator
523 MOV [LOADING],0 ; Flag to DSKERR
524 MOV SI,OFFSET RESGROUP:TRANVARS
525 MOV DI,OFFSET TRANGROUP:HEADCALL
529 REP MOVSW ; Transfer INFO to transient
531 MOV WORD PTR DS:[PDB_block_len],AX ; Adjust my own header
532 JMP DWORD PTR [TRANS]
534 ; Far call to REMCHECK for TRANSIENT
541 ;All registers preserved. Returns zero if media removable, NZ if fixed
542 ; AL is drive (0=DEF, 1=A,...)
547 MOV AH,GET_DEFAULT_DRIVE
553 INT 11H ;IBM EQUIP CALL
560 INC AL ; AL is now MAX floppy #
563 JBE SETREM ; Is an IBM floppy and so is removable
564 OR AL,AL ; Know AL is non-zero
580 ; Far call to HEADFIX for TRANSIENT
587 XOR BX,BX ; Clean up header
589 MOV DX,WORD PTR DS:[PDB_JFN_Table]
591 JZ CHK1 ; Stdin matches
594 MOV DS:[PDB_JFN_Table],CL ; Restore stdin
597 CMP CH,DH ; Stdout matches
601 MOV DS:[PDB_JFN_Table+1],CH ; Restore stdout
603 ADD BX,4 ; Skip 2,3,4
604 MOV CX,FilPerProc - 5 ; Already done 0,1,2,3,4
613 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
615 PUSH BX ; Set stdin to sterr, stdout to stderr
617 MOV AH,GET_CURRENT_PDB
618 INT int_command ; Get user's header
620 MOV AX,WORD PTR DS:[PDB_JFN_Table]
621 MOV [HANDLE01],AX ; Save user's stdin, stdout
622 MOV AL,DS:[PDB_JFN_Table+2]
624 MOV WORD PTR DS:[PDB_JFN_Table],AX ; Dup stderr
633 JMP LODCOM1 ; Memory already allocated
637 PUSH BX ; Restore stdin, stdout to user
639 MOV AH,GET_CURRENT_PDB
640 INT int_command ; Point to user's header
644 MOV WORD PTR DS:[PDB_JFN_Table],AX ; Stuff his old 0 and 1
649 ASSUME DS:RESGROUP,SS:RESGROUP
652 MOV DX,OFFSET RESGROUP:NOCOM
656 MOV DX,OFFSET RESGROUP:NEEDCOM
660 JNZ HOPELESS ;Non-removable media
662 MOV DX,OFFSET RESGROUP:DRVMSG
665 MOV DX,OFFSET RESGROUP:DEFMSG
668 MOV DX,OFFSET RESGROUP:PROMPT
670 CALL GetRawFlushedByte
673 ; flush world and get raw input
675 MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR RAW_CON_INPUT
676 INT int_command ; Get char without testing or echo
677 MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0
681 LOADCOM: ; Load in transient
682 INC BP ; Flag command read
683 MOV DX,OFFSET RESGROUP:COMSPEC
685 INT int_command ; Open COMMAND.COM
687 CMP AX,open_too_many_open_files
689 MOV DX,OFFSET RESGROUP:NOHANDMES
690 JMP FATALC ; Fatal, will never find a handle
698 MOV DX,OFFSET RESGROUP:TRANSTART
703 MOV CX,OFFSET TRANGROUP:TRANSPACEEND - 100H
708 ADD CX,OFFSET EGROUP:ZEXECCODEEND
723 INT int_command ; Close COMMAND.COM
726 JC WRONGCOM ; If error on READ
728 JZ RET10 ; Size matched
730 MOV DX,OFFSET RESGROUP:COMBAD
732 JMP SHORT LOADCOM ; Try again
734 CHKSUM: ; Compute transient checksum
738 MOV CX,OFFSET TRANGROUP:TRANDATAEND - 100H
751 SETVECT: ; Set useful vectors
752 MOV DX,OFFSET RESGROUP:LODCOM
753 MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 22H ; Set Terminate address
755 MOV DX,OFFSET RESGROUP:CONTC
756 MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H ; Set Ctrl-C address
758 MOV DX,OFFSET RESGROUP:DSKERR
759 MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 24H ; Set Hard Disk Error address
765 ; This TAIL segment is used to produce a PARA aligned label in the resident
766 ; group which is the location where the transient segments will be loaded
769 TAIL SEGMENT PUBLIC PARA
774 ; This TAIL segment is used to produce a PARA aligned label in the transient
775 ; group which is the location where the exec segments will be loaded
778 TRANTAIL SEGMENT PUBLIC PARA