summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/COMMAND/COMMAND2.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/COMMAND/COMMAND2.ASM')
-rw-r--r--v4.0/src/CMD/COMMAND/COMMAND2.ASM619
1 files changed, 619 insertions, 0 deletions
diff --git a/v4.0/src/CMD/COMMAND/COMMAND2.ASM b/v4.0/src/CMD/COMMAND/COMMAND2.ASM
new file mode 100644
index 0000000..0f6c5b5
--- /dev/null
+++ b/v4.0/src/CMD/COMMAND/COMMAND2.ASM
@@ -0,0 +1,619 @@
1 page 80,132
2; SCCSID = @(#)command2.asm 4.3 85/10/16
3; SCCSID = @(#)command2.asm 4.3 85/10/16
4TITLE COMMAND2 - resident code for COMMAND.COM part II
5NAME COMMAND2
6.XCREF
7.XLIST
8 INCLUDE DOSSYM.INC
9 INCLUDE comsw.asm
10 INCLUDE comequ.asm
11 INCLUDE resmsg.equ ;AN000;
12.LIST
13.CREF
14
15tokenized = FALSE
16
17CODERES SEGMENT PUBLIC BYTE ;AC000;
18CODERES ENDS
19
20DATARES SEGMENT PUBLIC BYTE
21 EXTRN append_state:word ;AN020;
22 EXTRN append_flag:byte ;AN020;
23 EXTRN COMDRV:BYTE
24 EXTRN comprmt1_block:byte ;AN000;
25 EXTRN comprmt1_subst:byte ;AN000;
26 EXTRN COMSPEC:BYTE
27 EXTRN cpdrv:byte
28 EXTRN envirseg:word
29 EXTRN EXTCOM:BYTE
30 EXTRN HANDLE01:WORD
31 EXTRN InitFlag:BYTE
32 EXTRN INT_2E_RET:DWORD ;AC000;
33 EXTRN IO_SAVE:WORD
34 EXTRN LOADING:BYTE
35 EXTRN LTPA:WORD
36 EXTRN MEMSIZ:WORD
37 EXTRN number_subst:byte ;AN000;
38 EXTRN OldTerm:DWORD ;AC000;
39 EXTRN PARENT:WORD ;AC000;
40 EXTRN PERMCOM:BYTE
41 EXTRN RDIRCHAR:BYTE
42 EXTRN RES_TPA:WORD
43 EXTRN RETCODE:WORD
44 EXTRN rsrc_xa_seg:word ;AN030;
45 EXTRN RSWITCHAR:BYTE
46 EXTRN SAVE_PDB:WORD
47 EXTRN SINGLECOM:WORD
48 EXTRN SUM:WORD
49 EXTRN TRANS:WORD
50 EXTRN TranVarEnd:BYTE
51 EXTRN TRANVARS:BYTE
52 EXTRN TRNSEG:WORD
53 EXTRN VERVAL:WORD
54DATARES ENDS
55
56BATARENA SEGMENT PUBLIC PARA ;AC000;
57BATARENA ENDS
58
59BATSEG SEGMENT PUBLIC PARA ;AC000;
60BATSEG ENDS
61
62ENVARENA SEGMENT PUBLIC PARA ;AC000;
63ENVARENA ENDS
64
65ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment
66ENVIRONMENT ENDS
67
68INIT SEGMENT PUBLIC PARA
69 EXTRN envsiz:word
70 EXTRN oldenv:word
71 EXTRN resetenv:byte
72 EXTRN usedenv:word
73INIT ENDS
74
75TAIL SEGMENT PUBLIC PARA
76TAIL ENDS
77
78TRANCODE SEGMENT PUBLIC PARA
79TRANCODE ENDS
80
81TRANDATA SEGMENT PUBLIC BYTE
82 EXTRN TRANDATAEND:BYTE
83TRANDATA ENDS
84
85TRANSPACE SEGMENT PUBLIC BYTE
86 EXTRN TRANSPACEEND:BYTE
87 EXTRN HEADCALL:DWORD
88TRANSPACE ENDS
89
90TRANTAIL SEGMENT PUBLIC PARA
91TRANTAIL ENDS
92
93RESGROUP GROUP CODERES,DATARES,BATARENA,BATSEG,ENVARENA,ENVIRONMENT,INIT,TAIL
94TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL
95
96; START OF RESIDENT PORTION
97
98CODERES SEGMENT PUBLIC BYTE ;AC000;
99
100 PUBLIC CHKSUM
101 PUBLIC endinit
102 PUBLIC GETCOMDSK2
103 PUBLIC INT_2E
104 PUBLIC LOADCOM
105 PUBLIC LODCOM
106 PUBLIC LODCOM1
107 PUBLIC RESTHAND
108 PUBLIC SAVHAND
109 PUBLIC SETVECT
110 PUBLIC THEADFIX
111 PUBLIC TREMCHECK
112 PUBLIC tjmp
113
114ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
115
116 EXTRN contc:near
117 EXTRN DSKERR:NEAR
118 EXTRN rstack:word
119;
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.
122;
123BADMEMERR: ; Allocation error loading transient
124 MOV DX,BMEMMES ;AC000; get message number
125FATALC:
126 PUSH CS
127 POP DS
128 ASSUME DS:ResGroup
129 invoke RPRINT
130;
131; If this is NOT a permanent (top-level) COMMAND, then we exit; we can't do
132; anything else!
133;
134 CMP PERMCOM,0
135 JZ FATALRET
136;
137; We are a permanent command. If we are in the process of the magic interrupt
138; (Singlecom) then exit too.
139;
140 CMP SINGLECOM,0 ; If PERMCOM and SINGLECOM
141 JNZ FATALRET ; Must take INT_2E exit
142;
143; Permanent command. We can't do ANYthing except halt.
144;
145 MOV DX,HALTMES ;AC000; get message number
146 invoke RPRINT
147 STI
148STALL:
149 JMP STALL ; Crash the system nicely
150
151FATALRET:
152 MOV DX,FRETMES ;AC000; get message number
153 invoke RPRINT
154FATALRET2:
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
158 MOV AX,[PARENT]
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
165 INT int_command
166
167RET_2E:
168 PUSH CS
169 POP DS
170ASSUME DS:RESGROUP,ES:NOTHING,SS:NOTHING
171 MOV [SINGLECOM],0 ; Turn off singlecom
172 MOV ES,[RES_TPA]
173 MOV AH,DEALLOC
174 INT int_command ; Free up space used by transient
175 MOV BX,[SAVE_PDB]
176 MOV AH,SET_CURRENT_PDB
177 INT int_command ; Current process is user
178 MOV AX,[RETCODE]
179 CMP [EXTCOM],0
180 JNZ GOTECODE
181 XOR AX,AX ; Internals always return 0
182GOTECODE:
183 MOV [EXTCOM],1 ; Force external
184 JMP [INT_2E_RET] ;"IRET"
185
186INT_2E: ; Magic command executer
187ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
188 POP WORD PTR [INT_2E_RET]
189 POP WORD PTR [INT_2E_RET+2] ;Get return address
190 POP AX ;Chuck flags
191 PUSH CS
192 POP ES
193 MOV DI,80H
194 MOV CX,64
195 REP MOVSW
196 MOV AH,GET_CURRENT_PDB
197 INT int_command ; Get user's header
198 MOV [SAVE_PDB],BX
199 MOV AH,SET_CURRENT_PDB
200 MOV BX,CS
201 INT int_command ; Current process is me
202 MOV [SINGLECOM],81H
203 MOV [EXTCOM],1 ; Make sure this case forced
204
205LODCOM: ; Termination handler
206 CMP [EXTCOM],0
207 jz lodcom1 ; if internal, memory already allocated
208 mov bx,0ffffh
209 MOV AH,ALLOC
210 INT int_command
211 CALL SetSize
212 ADD AX,20H
213 CMP BX,AX ; Is less than 512 byte buffer worth it?
214 JNC MEMOK
215BADMEMERRJ:
216 JMP BADMEMERR ; Not enough memory
217
218; SetSize - get transient size in paragraphs
219Procedure SetSize,NEAR
220 MOV AX,OFFSET TRANGROUP:TRANSPACEEND + 15
221 MOV CL,4
222 SHR AX,CL
223 return
224EndProc SetSize
225
226MEMOK:
227 MOV AH,ALLOC
228 INT int_command
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
232 AND AX, 0F000H
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
236 MOV DX, [RES_TPA]
237 ADD DX, BX ; Compute maximum address
238 CMP DX, AX ; Is 64K address out of range?
239 JBE BAD_TPA
240; Must have 64K of usable space.
241 SUB DX, AX ; Compute the usable space
242 CMP DX, 01000H ; Is space >= 64K ?
243 JAE LTPASET
244BAD_TPA:
245 MOV AX, [RES_TPA]
246LTPASET:
247 MOV [LTPA],AX ; Usable TPA is 64k buffer aligned
248 MOV AX, [RES_TPA] ; Actual TPA is buffer allocated
249 ADD BX,AX
250 MOV [MEMSIZ],BX
251 CALL SetSize
252 SUB BX,AX
253 MOV [TRNSEG],BX ; Transient starts here
254LODCOM1:
255 MOV AX,CS
256 MOV SS,AX
257ASSUME SS:RESGROUP
258 MOV SP,OFFSET RESGROUP:RSTACK
259 MOV DS,AX
260ASSUME DS:RESGROUP
261 CALL HEADFIX ; Make sure files closed stdin and stdout restored
262 XOR BP,BP ; Flag command ok
263 MOV AX,-1
264 XCHG AX,[VERVAL]
265 CMP AX,-1
266 JZ NOSETVER
267 MOV AH,SET_VERIFY_ON_WRITE ; AL has correct value
268 INT int_command
269NOSETVER:
270 CMP [SINGLECOM],-1
271 JNZ NOSNG
272 JMP FATALRET2 ; We have finished the single command
273NOSNG:
274 CALL CHKSUM ; Check the transient
275 CMP DX,[SUM]
276 JZ HAVCOM ; Transient OK
277BOGUS_COM:
278 MOV [LOADING],1 ; Flag DSKERR routine
279 CALL LOADCOM
280CHKSAME:
281
282 CALL CHKSUM
283 CMP DX,[SUM]
284 JZ HAVCOM ; Same COMMAND
285ALSO_BOGUS:
286 CALL WRONGCOM
287 JMP SHORT CHKSAME
288HAVCOM:
289 MOV AX,CHAR_OPER SHL 8
290 INT int_command
291 MOV [RSWITCHAR],DL
292 CMP DL,'/'
293 JNZ USESLASH
294 mov cl,'\'
295 MOV [RDIRCHAR],cl ; Select alt path separator
296USESLASH:
297 MOV [LOADING],0 ; Flag to DSKERR
298 MOV SI,OFFSET RESGROUP:TRANVARS
299 MOV DI,OFFSET TRANGROUP:HEADCALL
300 MOV ES,[TRNSEG]
301 CLD
302 MOV CX,OFFSET ResGroup:TranVarEnd
303 SUB CX,SI
304 REP MOVSB ; Transfer INFO to transient
305 MOV AX,[MEMSIZ]
306 MOV WORD PTR DS:[PDB_block_len],AX ; Adjust my own header
307
308; Just a public label so this spot can be found easily.
309tjmp:
310 JMP DWORD PTR [TRANS]
311
312; Far call to REMCHECK for TRANSIENT
313TREMCHECK PROC FAR
314 CALL REMCHECK
315 RET
316TREMCHECK ENDP
317
318REMCHECK:
319;All registers preserved. Returns ZF set if media removable, NZ if fixed
320; AL is drive (0=DEF, 1=A,...).
321 SaveReg <AX,BX>
322 MOV BX,AX
323 MOV AX,(IOCTL SHL 8) + 8
324 INT 21h
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.
331 jmp SHORT ResRegs
332RCcont:
333 AND AX,1
334 NOT AX
335ResRegs:
336 RestoreReg <BX,AX>
337 return
338
339; Far call to HEADFIX for TRANSIENT
340THEADFIX PROC FAR
341 CALL HEADFIX
342 RET
343THEADFIX ENDP
344
345HEADFIX:
346 CALL SETVECT
347 XOR BX,BX ; Clean up header
348 MOV CX,[IO_SAVE]
349 MOV DX,WORD PTR DS:[PDB_JFN_Table]
350 CMP CL,DL
351 JZ CHK1 ; Stdin matches
352 MOV AH,CLOSE
353 INT int_command
354 MOV DS:[PDB_JFN_Table],CL ; Restore stdin
355CHK1:
356 INC BX
357 CMP CH,DH ; Stdout matches
358 JZ CHKOTHERHAND
359 MOV AH,CLOSE
360 INT int_command
361 MOV DS:[PDB_JFN_Table+1],CH ; Restore stdout
362CHKOTHERHAND:
363 ADD BX,4 ; Skip 2,3,4
364 MOV CX,FilPerProc - 5 ; Already done 0,1,2,3,4
365CLOSELOOP:
366 MOV AH,CLOSE
367 INT int_command
368 INC BX
369 LOOP CLOSELOOP
370 push ds ;AN020; save data segment
371 push cs ;AN020; Get local segment into DS
372 pop ds ;AN020;
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
377 int 2fh ;AN020;
378 mov append_flag,0 ;AN020; Set append flag to invalid
379append_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;
386 pop es ;AN030;
387 mov [rsrc_xa_seg],no_xa_seg ;AN030; reset to no segment
388xa_fix_end:
389 pop ds ;AN020; get data segment back
390 return
391
392SAVHAND:
393ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
394 PUSH DS
395 PUSH BX ; Set stdin to sterr, stdout to stderr
396 PUSH AX
397 MOV AH,GET_CURRENT_PDB
398 INT int_command ; Get user's header
399 MOV DS,BX
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
404 MOV AH,AL
405 MOV WORD PTR DS:[BX],AX ; Dup stderr
406 POP AX
407 POP BX
408 POP DS
409 return
410
411ASSUME DS:RESGROUP
412GETCOMDSK2:
413 CALL GETCOMDSK
414 JMP LODCOM1 ; Memory already allocated
415
416RESTHAND:
417 PUSH DS
418 PUSH BX ; Restore stdin, stdout to user
419 PUSH AX
420 MOV AH,GET_CURRENT_PDB
421 INT int_command ; Point to user's header
422 MOV AX,[HANDLE01]
423 MOV DS,BX
424ASSUME DS:NOTHING
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
427 POP AX
428 POP BX
429 POP DS
430 return
431ASSUME DS:RESGROUP,SS:RESGROUP
432
433HOPELESS:
434 MOV DX,COMBAD ;AC000;
435 JMP FATALC
436
437GETCOMDSK:
438 mov al,[comdrv]
439 CALL REMCHECK
440 jNZ HOPELESS ;Non-removable media
441getcomdsk3:
442 cmp dx,combad ;AC000;
443 jnz getcomdsk4
444 mov dx,combad ;AN000; get message number
445 invoke RPRINT ; Say command is invalid
446getcomdsk4:
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
450 int 21h ;g
451 add al,"A" ;g convert to ascii
452 mov [cpdrv],al ;g put in message to print out
453
454users_drive: ;g
455 mov dx,comprmt1 ;AC000; Prompt for diskette containing command
456IF tokenized
457 or byte ptr [si],80h
458endif
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;
462 invoke rprint
463if tokenized
464 and byte ptr [si],NOT 80h
465endif
466 mov dx,prompt ;AN047; Tell the user to strike a key
467 invoke rprint ;AN047;
468 CALL GetRawFlushedByte
469 return
470
471; flush world and get raw input
472GetRawFlushedByte:
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
476 INT int_command
477 return
478
479LOADCOM: ; Load in transient
480 INC BP ; Flag command read
481 MOV DX,OFFSET RESGROUP:COMSPEC
482 MOV AX,OPEN SHL 8
483 INT int_command ; Open COMMAND.COM
484 JNC READCOM
485 CMP AX,error_too_many_open_files
486 JNZ TRYDOOPEN
487 MOV DX,NOHANDMES ;AC000;
488 JMP FATALC ; Fatal, will never find a handle
489
490TRYDOOPEN:
491 CALL GETCOMDSK
492 JMP LOADCOM
493
494READCOM:
495 MOV BX,AX ; Handle
496 MOV DX,OFFSET RESGROUP:TRANSTART
497 XOR CX,CX ; Seek loc
498 MOV AX,LSEEK SHL 8
499 INT int_command
500 JC WRONGCOM1
501 MOV CX,OFFSET TRANGROUP:TRANSPACEEND - 100H
502
503 PUSH DS
504 MOV DS,[TRNSEG]
505ASSUME DS:NOTHING
506 MOV DX,100H
507 MOV AH,READ
508 INT int_command
509 POP DS
510ASSUME DS:RESGROUP
511WRONGCOM1:
512 PUSHF
513 PUSH AX
514 MOV AH,CLOSE
515 INT int_command ; Close COMMAND.COM
516 POP AX
517 POPF
518 JC WRONGCOM ; If error on READ
519 CMP AX,CX
520 retz ; Size matched
521WRONGCOM:
522 MOV DX,COMBAD ;AC000;
523 CALL GETCOMDSK
524 JMP LOADCOM ; Try again
525
526CHKSUM: ; Compute transient checksum
527 PUSH DS
528 MOV DS,[TRNSEG]
529 MOV SI,100H
530 MOV CX,OFFSET TRANGROUP:TranDataEnd - 100H
531
532CHECK_SUM:
533 CLD
534 SHR CX,1
535 XOR DX,DX
536CHK:
537 LODSW
538 ADD DX,AX
539 ADC DX,0
540 LOOP CHK
541 POP DS
542 return
543
544SETVECT: ; 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
549 INT int_command
550 MOV DX,OFFSET RESGROUP:CONTC
551 INC AL
552 INT int_command
553 MOV DX,OFFSET RESGROUP:DSKERR
554 INC AL
555 INT int_command
556 return
557
558
559;
560; This routine moves the environment to a newly allocated segment
561; at the end of initialization
562;
563
564ENDINIT:
565 push ds ;g save segments
566 push es ;g
567 push cs ;g get resident segment to DS
568 pop ds ;g
569 ASSUME DS:RESGROUP
570 mov cx,usedenv ;g get number of bytes to move
571 mov es,envirseg ;g get target environment segment
572
573 ASSUME ES:NOTHING
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;
578 xor di,di ;g ;AM067;
579 cld ;g make sure we move the right way! ;AM067;
580 rep movsb ;g move it ;AM067;
581 xor ax,ax ;g ;AM067;
582 stosb ;g make sure there are double 0 at end ;AM067;
583
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
588 mov ah,SETBLOCK ;eg
589 int int_command ;eg
590 pop es ;eg
591
592noreset:
593 mov InitFlag,FALSE ;AC042; Turn off init flag
594 pop es ;g
595 pop ds ;g
596 jmp lodcom ;g allocate transient
597
598CODERES ENDS
599
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
602; initial.
603
604TAIL SEGMENT PUBLIC PARA
605 ORG 0
606 PUBLIC TranStart
607TRANSTART LABEL WORD
608TAIL ENDS
609
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
612; initial.
613
614TRANTAIL SEGMENT PUBLIC PARA
615 ORG 0
616EXECSTART LABEL WORD
617TRANTAIL ENDS
618
619 END