2 ; SCCSID = @(#)init.asm 4.13 85/11/03
3 ; SCCSID = @(#)init.asm 4.13 85/11/03
4 TITLE COMMAND Initialization
11 include doscntry
.inc ;AC000;
14 include resmsg
.equ
;AN000;
19 ENVIRONSIZ EQU
0A0H ;Must agree with values in EVIRONMENT segment
24 KOREA_COUNTRY_CODE EQU
82
26 CODERES
SEGMENT PUBLIC BYTE ;AC000;
35 DATARES
SEGMENT PUBLIC BYTE ;AC000;
36 EXTRN abort_char
:byte ;AN000;
37 EXTRN append_state
:word ;AN042;
38 EXTRN BADFAT_OP_SEG
:WORD ;AN000;
43 EXTRN com_xlat_addr
:word
45 EXTRN COMPRMT1_SEG
:WORD ;AN000;
46 EXTRN COMPRMT1_SEG2
:WORD ;AN000;
48 EXTRN comspec_print
:word
49 EXTRN comspec_end
:word
51 EXTRN crit_msg_off
:word ;AN000;
52 EXTRN crit_msg_seg
:word ;AN000;
53 EXTRN critical_msg_start
:byte ;AN000;
54 EXTRN DATARESEND
:BYTE ;AC000;
55 EXTRN dbcs_vector_addr
:word ;AN000;
56 EXTRN DEVE_OP_SEG
:WORD ;AN000;
57 EXTRN DEVE_OP_SEG2
:WORD ;AN000;
58 EXTRN disp_class
:byte ;AN000;
59 EXTRN DRVNUM_OP_SEG
:WORD ;AN000;
60 EXTRN DRVNUM_OP_SEG2
:WORD ;AN000;
63 EXTRN ERR15_OP_SEG
:WORD ;AN000;
64 EXTRN ERR15_OP_SEG2
:WORD ;AN000;
65 EXTRN ERR15_OP_SEG3
:WORD ;AN000;
66 EXTRN extended_msg_start
:byte ;AN000;
67 EXTRN extmsgend
:byte ;AN000;
69 EXTRN fucase_addr
:word ;AN000;
72 EXTRN LTPA
:WORD ;AC000;
74 EXTRN MYSEG
:WORD ;AC000;
78 EXTRN number_subst
:byte ;AN000;
81 ;AD060; EXTRN pars_msg_off:word ;AN000;
82 ;AD060; EXTRN pars_msg_seg:word ;AN000;
83 EXTRN parse_msg_start
:byte ;AN000;
84 EXTRN parsemes_ptr
:word ;AN000;
87 EXTRN resmsgend
:word ;AN000;
95 BATARENA
SEGMENT PUBLIC PARA
;AC000;
98 BATSEG
SEGMENT PUBLIC PARA
;AC000;
101 ENVARENA
SEGMENT PUBLIC PARA
;AC000;
104 ENVIRONMENT
SEGMENT PUBLIC PARA
; Default COMMAND environment
107 EXTRN PATHSTRING
:BYTE
110 TAIL
SEGMENT PUBLIC PARA
114 TRANCODE
SEGMENT PUBLIC BYTE ;AC000;
116 EXTRN printf_init
:far
119 TRANSPACE
SEGMENT PUBLIC BYTE ;AC000;
120 EXTRN TRANSPACEEND
:BYTE
123 ; This is the area used for the autoexec.bat file. BATARENA is a pad for the
124 ; the address mark placed by DOS.
126 BATARENA
SEGMENT PUBLIC PARA
129 DB 10h
DUP (?
) ;Pad for memory allocation addr mark
133 BATSEG
SEGMENT PUBLIC PARA
;Autoexec.bat segment
136 initbat batchsegment
<> ;batch segment
137 DB 31 DUP (0) ;reserve area for batch file name & pad
141 ; *******************************************************************
142 ; START OF INIT PORTION
143 ; This code is overlayed the first time the TPA is used.
145 INIT
SEGMENT PUBLIC PARA
151 EXTRN command_c_syn
:byte ;AN000;
152 EXTRN command_d_syn
:byte ;AN000;
153 EXTRN command_e_syn
:byte ;AN000;
154 EXTRN command_f_syn
:byte ;AN000;
155 EXTRN command_m_syn
:byte ;AN000;
156 EXTRN command_p_syn
:byte ;AN000;
157 EXTRN comnd1_syn
:word ;AN000;
158 EXTRN comnd1_addr
:dword ;AN000;
160 EXTRN comspstring
:byte
161 EXTRN dswitch
:byte ;AN018;
166 EXTRN eswitch
:byte ;AN018;
167 EXTRN ext_msg
:byte ;AN000;
171 EXTRN init_parse
:dword ;AN054;
172 EXTRN INTERNAT_INFO
:BYTE ;AN000; 3/3/KK
173 EXTRN KAUTOBAT
:byte ;AN000; 3/3/KK
176 EXTRN num_positionals
:word ;AN000;
178 EXTRN old_parse_ptr
:word ;AN057;
179 EXTRN parse_command
:byte ;AN000;
180 EXTRN pars_msg_off
:word ;AN060;
181 EXTRN pars_msg_seg
:word ;AN060;
183 EXTRN resetenv
:word ;AC000;
186 EXTRN triage_add
:dword ;AC000;
192 ;AD054; EXTRN SYSPARSE:NEAR
195 PUBLIC init_contc_specialcase
197 ASSUME
CS:RESGROUP
,DS:RESGROUP
,ES:RESGROUP
,SS:RESGROUP
204 MOV SP,OFFSET RESGROUP
:RSTACK
; MUST be first instruction
206 CALL SYSLOADMSG
;AN000; check dos version
207 JNC OKDOS
;AN000; if no problem - continue
209 mov ax,badver
;AN000; set DOS version
210 invoke sysdispmsg
;AN000; must be incorrect version
212 cmp es:[PDB_Parent_PID
],AX ; If command is its own parent,
213 here: ; loop forever.
215 int 20h
; Otherwise, exit.
218 ; Turn APPEND off during initialization processing
221 mov ax,AppendInstall
;AN042; see if append installed
223 cmp al,0 ;AN042; append installed?
224 je set_msg_addr
;AN042; no - continue
225 mov ax,AppendDOS
;AN042; see if append DOS version right
227 cmp ax,-1 ;AN042; append version correct?
228 jne set_msg_addr
;AN042; no - continue
229 mov ax,AppendGetState
;AN042; Get the state of Append
231 mov append_state
,bx ;AN042; save append state
232 xor bx,bx ;AN042; clear out state
233 mov ax,AppendSetState
;AN042; Set the state of Append
234 int 2fh
;AN042; set everything off
238 ; Get addresses of old critical and parse errors and save so they can
239 ; be reset if COMMAND needs to exit
242 push es ;AN000; SAVE ES DESTROYED BY INT 2FH
243 ;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh
244 ;AD060; mov al,message_2f ;AN000; call for message retriever
245 mov ax,(multdos
shl 8 or message_2f
);AN060; set up to call DOS through int 2fh
246 mov dl,get_parse_msg
;AN000; get parse message address
248 mov cs:pars_msg_seg
,es ;AN000; save returned segment
249 mov cs:pars_msg_off
,di ;AN000; save returned offset
251 ;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh
252 ;AD060; mov al,message_2f ;AN000; call for message retriever
253 mov ax,(multdos
shl 8 or message_2f
);AN060; set up to call DOS through int 2fh
254 mov dl,get_critical_msg
;AN000; get critical error message address
256 mov cs:crit_msg_seg
,es ;AN000; save returned segment
257 mov cs:crit_msg_off
,di ;AN000; save returned offset
258 pop es ;AN000; RESTORE ES DESTROYED BY INT 2FH
261 ; Set addresses of critical and parse errors in this level of COMMAND
264 ;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh
265 ;AD060; mov al,message_2f ;AN000; call for message retriever
266 ;AD060; mov dl,set_parse_msg ;AN000; set up parse message address
267 mov di,offset resgroup
:parse_msg_start
;AN000; start address
268 ;AD060; int 2fh ;AN000;
269 call set_parse_2f
;AN060; set parse error address
272 ;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh
273 ;AD060; mov al,message_2f ;AN000; call for message retriever
274 mov ax,(multdos
shl 8 or message_2f
);AN060; set up to call DOS through int 2fh
275 mov dl,set_critical_msg
;AN000; set up critical error message address
276 mov di,offset resgroup
:critical_msg_start
;AN000; start address
279 mov di,offset resgroup
:dataresend
+15 ;AN000; get address of resident end
280 mov [resmsgend
],di ;AN000; save it
281 call sysloadmsg
;AN000; load message addresses
282 call get_msg_ptr
;AN000; set up pointers to some translated chars
283 mov ah,GetExtCntry
;g get extended country information
284 mov al,2 ;g minor function - ucase table
287 mov cx,5 ;g number of bytes we want
288 mov di,offset resgroup
:com_xlat_addr
;g buffer to put address in
291 mov ah,GetExtCntry
;AN000; get extended country info
292 mov al,4 ;AN000; get file ucase table
295 mov cx,5 ;AN000; number of bytes we want
296 mov di,offset resgroup
:fucase_addr
;AN000; buffer for address
297 int int_command
;AN000;
299 mov dx,offset resgroup
:transtart
+15 ;eg get end of init code
300 mov cl,4 ;eg change to paragraphs
302 mov ax,cs ;eg get current segment
303 add ax,dx ;eg calculate segment of end of init
304 mov [initend
],ax ;eg save this
307 mov ax, (ECS_call
SHL 8) OR GetLeadBTbl
;AN000; get dbcs vector
308 int int_command
;AN000;
309 mov bx,ds ;AN000; get segment to bx
311 mov dbcs_vector_addr
,si ;AN000; save address of
312 mov dbcs_vector_addr
+2,bx ;AN000; dbcs vector
315 mov ax,word ptr ds:[PDB_Parent_PID
] ; Init PARENT so we can exit
316 mov [PARENT
],ax ; correctly.
317 MOV AX,WORD PTR DS:[PDB_Exit
]
318 MOV WORD PTR OldTerm
,AX
319 MOV AX,WORD PTR DS:[PDB_Exit
+2]
320 MOV WORD PTR OldTerm
+2,AX
322 MOV AX,OFFSET RESGROUP
:ENVIREND
+ 15
323 MOV CL,4 ; ax = size of resident part of
324 SHR AX,CL ; command in paragraphs. Add
325 MOV CX,CS ; this to CS and you get the
326 ADD AX,CX ; segment of the TPA.
328 MOV [RES_TPA
], AX ; Temporarily save the TPA segment
330 ADD AX, 01000H ; Round up to next 64K boundary
331 JNC TPASET
; Memory wrap if carry set
334 MOV [LTPA
],AX ; Good enough for the moment
335 MOV AX,WORD PTR DS:[PDB_block_len
] ; ax = # of paras given to command
337 MOV [MYSEG1
],DS ; These 3 variables are used as part of
338 MOV [MYSEG2
],DS ; 3 long ptrs that the transient will
339 MOV [MYSEG
],DS ; use to call resident routines.
340 MOV [MEMSIZ
],AX ; Needed for execing other programs
342 ; Compute maximum size of environment
344 MOV EnvMax
,(Environsiz
+ 15) / 16 + (EnvMaximum
-zero
+ 15)/16 - 1
346 ; Compute minimum size of environment
349 MOV EnvSiz
, ENVSML
/ 16
351 MOV DX,OFFSET TRANGROUP
:TRANSPACEEND
+ 15 ; dx = size of transient
352 MOV CL,4 ; in paragraphs.
354 mov [trnsize
],dx ;eg save size of transient in paragraphs
356 SUB AX,DX ; max seg addr - # para's needed for transient
357 MOV [TRNSEG
],AX ; = seg addr to load the transient at.
358 MOV AX,DS:[PDB_environ
] ; ax = environment segment
359 OR AX,AX ; If there is no environment segment,
360 JZ BUILDENV
; go compute one.
361 INC BYTE PTR [CHUCKENV
] ; Flag no new ENVIRONSEG to set up
362 JMP SHORT ENVIRONPASSED
; Otherwise one was passed to us.
364 BUILDENV: ; (this label isn't very accurate)
365 MOV AX,OFFSET RESGROUP
:PATHSTRING
; Compute the segment of the
366 MOV CL,4 ; environment and put it in
372 MOV [ENVIRSEG
],AX ; Save the environment's segment and
373 MOV ES,AX ; load into es.
374 ASSUME
ES:ENVIRONMENT
377 MOV AX,CHAR_OPER
SHL 8 ; Get the switch character and store it
378 INT int_command
; in RSWITCHAR.
381 CMP DL,fslash
; If backslashes are being used as the
382 JNZ IUSESLASH
; path separator, change the forward
383 mov al,bslash
; slash in COMSPECT and ECOMSPEC (if
384 MOV [COMSPECT
],al ; there is a new ENVIRONSEG) to
385 CMP BYTE PTR [CHUCKENV
],0 ; backslash.
387 MOV ES:[ECOMSPEC
],al ;eg
391 ; Initialize the command drive
393 MOV AH,Get_Default_Drive
398 MOV AL,BYTE PTR DS:[FCB
] ; al = default drive number for command
400 JZ NoComDrv
; no drive specified
404 ADD AL,40H
; Convert number to uppercase character
407 CMP BYTE PTR [CHUCKENV
],0 ; If a new environment is being built,
408 JNZ NOTWIDENV
; move the default comspec string in it
409 PUSH DS ; 2 bytes to make room for a drivespec.
410 PUSH ES ; The drivespec is in ax and is copied
411 POP DS ; on to the front of the string.
412 MOV DI,OFFSET ENVIRONMENT
:ECOMSPEC
+ ENVIRONSIZ2
- 1 ;eg
413 MOV SI,OFFSET ENVIRONMENT
:ECOMSPEC
+ ENVIRONSIZ2
- 3 ;eg
415 MOV CX,ENVIRONSIZ2
- 2
418 MOV WORD PTR ES:[ECOMSPEC
],AX
421 CLD ; Add the drivespec to the string
422 MOV WORD PTR [AUTOBAT
],AX ; used to reference autoexec.bat
423 MOV WORD PTR [KAUTOBAT
],AX ;AN000; used to reference kautoexe.bat 3/3/KK
426 INVOKE SETVECT
; Set interrupt vectors 22h, 23h, & 24h
428 ;*********************************
429 ; PARSING STARTS HERE
430 ;*********************************
432 push cs ;AN000; get local segment
433 push cs ;AN000; into DS,ES
437 ASSUME
DS:RESGROUP
,ES:RESGROUP
;AN000;
439 MOV SI,80H
;AC000; get command line
440 LODSB ;AC000; get length of line
441 MOV DI,SI ;AN000; get line position in DI
442 XOR AH,AH ;AC000; ax = length of command line
444 ; Insure that the command line correctly ends with a CR
446 ADD DI,AX ;AC000; go to end of command line
447 MOV BYTE PTR [DI],0Dh ;AC000; insert a carriage return
448 xor cx,cx ;AC000; clear cx
449 mov num_positionals
,cx ;AC000; initialize positionals
451 ; Scan the command line looking for the parameters
455 mov di,offset resgroup
:parse_command
;AN000; Get address of parse_command
456 mov cx,num_positionals
;AN000; Get number of positionals
457 xor dx,dx ;AN000; clear dx
458 mov old_parse_ptr
,si ;AN057; save position before calling parser
459 call init_parse
;AN054; call parser
460 mov num_positionals
,cx ;AN000; Save number of positionals
461 cmp ax,end_of_line
;AC000; are we at end of line?
462 jz ArgsDoneJ3
;AC000; yes - exit
463 cmp ax,result_no_error
;AN000; did an error occur
464 jz parse_cont
;AN000; no - continue
467 ; Before issuing error message - make sure switch is not /C
471 push si ;AN057; save line position
472 push ax ;AN057; save error number
473 cmp ax,BadSwt_Ptr
;AN057; Was error invalid switch?
474 jnz parse_line_error_disp
;AN057; No - just issue message
475 mov di,si ;AN057; Get terminating pointer in DI
476 mov si,old_parse_ptr
;AN057; Get starting pointer in SI
479 cmp si,di ;AN057; at end of parsed parameter?
480 jz parse_line_error_disp
;AN057; Yes - just display message
482 cmp al,space
;AN057; Skip blank spaces
483 jz init_chk_delim
;AN057;
484 cmp al,tab_chr
;AN057; Skip tab characters
485 jz init_chk_delim
;AN057;
487 cmp al,[rswitchar
] ;AN057; Switch?
488 jnz parse_line_error_disp
;AN057; No - just issue message
489 lodsb ;AN057; Get the char after the switch
490 invoke itestkanj
;AN057; Is it DBCS?
491 jnz parse_line_error_disp
;AN057; Yes - can't be /C
492 invoke iupconv
;AN057; upper case it
493 cmp al,scswitch
;AN057; it is /C?
494 jnz parse_line_error_disp
;AN057;
495 pop dx ;AN057; even up stack
496 pop dx ;AN057; even up stack
497 jmp setSSwitch
;AN057; Yes - go set COMMAND /C
499 parse_line_error_disp:
500 pop ax ;AN057; restore error number
501 pop si ;AN057; restore line position
502 mov disp_class
,parse_msg_class
;AN000; set up parse error msg class
503 mov dx,ax ;AN000; get message number
504 call print_message
;AN000; issue error message
505 jmp short parse_command_line
;AN000; continue parsing
509 ; See if a switch was entered
512 cmp comnd1_syn
,offset resgroup
:command_f_syn
;AC000; was /F entered?
513 jz SetFSwitch
;AC000; yes go set fail switch
514 cmp comnd1_syn
,offset resgroup
:command_p_syn
;AC000; was /P entered?
515 Jz SetPSwitch
;AC000; yes go set up PERMCOM
516 cmp comnd1_syn
,offset resgroup
:command_d_syn
;AC000; was /D entered?
517 jz SetDSwitch
;AC000; yes go set date switch
518 cmp comnd1_syn
,offset resgroup
:command_c_syn
;AC000; was /C entered?
519 jz SetSSwitch
;AC000; yes go set up SINGLECOM
520 cmp comnd1_syn
,offset resgroup
:command_e_syn
;AC000; was /E entered?
521 jz SetESwitch
;AC000; yes go set up environment
522 cmp comnd1_syn
,offset resgroup
:command_m_syn
;AN000; was /MSG entered?
523 jz SetMSwitchjmp
;AN000; yes go set up message flag
524 jmp chkotherargs
;AC000; Must be something else
526 SetMSwitchjmp: ;AN018; long jump needed
527 jmp SetMswitch
;AN018;
529 ArgsdoneJ3: ;AN018; long jump needed
533 cmp fFail
,-1 ;AN018; has fail switch been set?
534 jnz failok
;AN018; no - set it
535 mov ax,moreargs_ptr
;AN018; set up too many arguments
536 jmp parse_line_error
;AN018; go issue error message
539 MOV fFail
,-1 ;AC000; fail all INT 24s.
540 JMP parse_command_line
;AC000;
544 ; We have a permanent COMMAND switch /P. Flag this and stash the
545 ; termination address.
547 cmp [permcom
],0 ;AN018; has /p switch been set?
548 jz permcomok
;AN018; no - set it
549 mov ax,moreargs_ptr
;AN018; set up too many arguments
550 jmp parse_line_error
;AN018; go issue error message
554 MOV WORD PTR [oldTerm
],OFFSET RESGROUP
:LODCOM
555 MOV WORD PTR [oldTerm
+2],DS
557 ; Make sure that we display the date and time. If the flag was not
558 ; initialized, set it to indicate yes, do prompt.
560 CMP BYTE PTR [PRDATTM
],-1
561 JNZ parse_command_line_jmp
;AC018; keep parsing
562 MOV BYTE PTR [PRDATTM
],0 ; If not set explicit, set to prompt
564 Parse_command_line_jmp: ;AN018;
565 JMP parse_command_line
;AC000; keep parsing
572 ; Flag no date/time prompting.
574 cmp dswitch
,0 ;AN018; has /D switch been set?
575 jz setdateok
;AN018; no - set it
576 mov ax,moreargs_ptr
;AN018; set up too many arguments
577 jmp parse_line_error
;AN018; go issue error message
580 inc dswitch
;AN018; indicate /D entered
581 MOV BYTE PTR [PRDATTM
],1 ; User explicitly says no date time
582 JMP parse_command_line
;AC000; continue parsing
586 ; Set up pointer to command line, flag no date/time and turn off singlecom.
588 MOV [SINGLECOM
],SI ; Point to the rest of the command line
589 MOV [PERMCOM
],0 ; A SINGLECOM must not be a PERMCOM
590 MOV BYTE PTR [PRDATTM
],1 ; No date or time either, explicit
593 ; Look for environment-size setting switch
595 ; The environment size is represented in decimal bytes and is
596 ; converted into pargraphs (rounded up to the next paragraph).
600 cmp eswitch
,0 ;AN018; has fail switch been set?
601 jz eswitchok
;AN018; no - set it
602 mov ax,moreargs_ptr
;AN018; set up too many arguments
603 jmp parse_line_error
;AN018; go issue error message
606 inc eswitch
;AN018; indicate /E entered
607 mov di,offset resgroup
:comnd1_addr
;AN000; get number returned
608 mov bx,word ptr [di] ;AN000; into bx
610 ADD BX, 0FH ; Round up to next paragraph
611 mov cl,4 ;AC000; convert to pargraphs
612 SHR BX, cl ;AC000; by right 4
614 MOV EnvSiz
,BX ; EnvSiz is in paragraphs
615 JMP parse_command_line
;AC000; continue parsing command line
618 cmp ext_msg
,set_extended_msg
;AN018; has /MSG switch been set?
619 jnz setMswitchok
;AN018; no - set it
620 mov ax,moreargs_ptr
;AN018; set up too many arguments
621 jmp parse_line_error
;AN018; go issue error message
623 MOV Ext_msg
,set_extended_msg
;AN000; set /MSG switch
624 JMP parse_command_line
;AN000; keep parsing
630 ; We have a non-switch character here.
634 push si ;AC000; save place in command line
635 lds si,comnd1_addr
;AN000; get address of filespec
636 assume
ds:nothing
;AN054;
638 mov dx,si ;AN000; put in dx also
639 MOV AX,(OPEN
SHL 8) OR 2 ; Read and write
641 JC CHKSRCHSPEC
; Wasn't a file
649 MOV AH,CLOSE
; Close initial handle, wasn't a device
655 OR DL,3 ; Make sure has CON attributes
656 MOV AX,(IOCTL
SHL 8) OR 1
658 JC BADSETCON
;AN022; Can't set attributes - quit
659 MOV DX,BX ; Save new handle
660 ;eg POP BX ; Throw away saved SI
661 ;eg POP BX ; Throw away saved CX
666 RCCLLOOP: ; Close 0,1 and 2
671 MOV BX,DX ; New device handle
673 INT int_command
; Dup to 0
675 INT int_command
; Dup to 1
677 INT int_command
; Dup to 2
679 INT int_command
; Close initial handle
681 pop si ;AN000; restore position of command line
683 JMP parse_command_line
;AC000; continue parsing
685 CHKSRCHSPEC: ; Not a device, so must be directory spec
687 MOV BYTE PTR [CHUCKENV
],0 ; If search specified -- no inheritance
688 MOV AX,OFFSET RESGROUP
:PATHSTRING
; Figure environment pointer
697 push si ;AN000; remember location of file
698 xor cx,cx ;AN000; clear cx for counting
701 lodsb ;AN000; get a character
702 inc cx ;AN000; increment counter
703 cmp al,end_of_line_out
;AN000; are we at end of line?
704 jnz countloop
;AN000; no - keep counting
707 dec si ;AN000; move back one
708 MOV BYTE PTR [SI],al ;AN000; put a space at end of line
709 pop si ;AC000; get location back
727 PUSH DS ;AN054; Make sure we have
728 PUSH CS ;AN054; local DS for
729 POP DS ;AN054; ITESTKANJ
731 POP DS ;AN054; restore PARSER DS
744 PUSH CS ;AN054; Get local segment
746 assume
ds:resgroup
;AN054;
749 MOV SI,OFFSET RESGROUP
:COMSPECT
756 JNZ INOTROOT
; Last char was KANJI second byte, might be '\'
761 INC SI ; Don't make a double /
767 MOV DX,[ECOMLOC
] ; Now lets make sure its good!
772 INT int_command
; Open COMMAND.COM
774 JC SETCOMSRBAD
; No COMMAND.COM here
777 INT int_command
; Close COMMAND.COM
783 assume
ds:resgroup
;AN054;
786 PUSH CS ;AN000; Make sure local ES is
787 POP ES ;AN000; restored
788 JMP parse_command_line
;AC000; continue parsing command line
791 MOV DX,BADCOMLKMES_ptr
;AC000; get message number
795 mov dx,BADCOMACCMES_ptr
;AC000; get error message number
798 MOV SI,OFFSET RESGROUP
:COMSPECT
801 REP MOVSB ; Get my default back
803 JMP SHORT SETCOMSRRET
805 ;*********************************
807 ;*********************************
810 mov es,[envirseg
] ;AC000; get environment back
811 ASSUME
ES:ENVIRONMENT
;AN000;
812 ;AD060; cmp ext_msg,set_extended_msg ;AN000; was /msg specified?
813 ;AD060; jnz check_permcom ;AN000; No, go check permcom
814 ;AD060; cmp [permcom],0 ;AN000; Yes - was permcom set?
815 ;AD060; jz permcom_error ;AN000; No - error cannot have /MSG without /P
817 ;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh
818 ;AD060; mov al,message_2f ;AN000; call for message retriever
819 ;AD060; mov dl,set_extended_msg ;AN000; set up extended error message address
820 ;AD060; push es ;AN016; save environment segment
821 ;AD060; push cs ;AN016; get local segment to ES
822 ;AD060; pop es ;AN016;
823 ;AD060; mov di,offset resgroup:extended_msg_start ;AN000; start address
824 ;AD060; int 2fh ;AN000;
825 ;AD060; pop es ;AN016; restore environment segment
826 ;AD060; mov di,offset resgroup:extmsgend+15 ;AN000; get address of resident end
827 ;AD060; mov [resmsgend],di ;AN000; save it
828 ;AD060; call sysloadmsg ;AN000; load message addresses
829 ;AD060; jmp short process_permcom ;AN000; now go process /P switch
831 ;AD060;permcom_error:
832 ;AD060; mov disp_class,parse_msg_class ;AN000; set up parse error msg class
833 ;AD060; mov dx,LessArgs_Ptr ;AN000; get message number for "Required parameter missing"
834 ;AD060; call print_message ;AN000; issue error message
835 ;AD060; jmp short comreturns ;AN000; we already know /P wasn't entered
837 ;AD060;check_permcom:
841 ;AD060;process_permcom:
842 PUSH ES ; Save environment pointer
843 MOV AH,SET_CURRENT_PDB
846 INT int_command
; Current process is me
847 MOV DI,PDB_Exit
; Diddle the addresses in my header
848 MOV AX,OFFSET RESGROUP
:LODCOM
852 MOV AX,OFFSET RESGROUP
:CONTC
856 MOV AX,OFFSET RESGROUP
:DskErr
860 MOV WORD PTR DS:[PDB_Parent_PID
],DS ; Parent is me forever
862 MOV DX,OFFSET RESGROUP
:INT_2E
863 MOV AX,(SET_INTERRUPT_VECTOR
SHL 8) OR 02EH
864 INT int_command
;Set magic interrupt
865 POP ES ;Remember environment
868 MOV AX,WORD PTR DS:[PDB_Parent_PID
]
869 MOV [PARENT
],AX ; Save parent
870 MOV WORD PTR DS:[PDB_Parent_PID
],DS ; Parent is me
871 MOV AX,WORD PTR DS:[PDB_JFN_Table
]
872 MOV [IO_SAVE
],AX ; Get the default stdin and out
873 MOV WORD PTR [COM_PTR
+2],DS ; Set all these to resident
874 MOV WORD PTR [COM_FCB1
+2],DS
875 MOV WORD PTR [COM_FCB2
+2],DS
876 MOV DI,OFFSET RESGROUP
:COMSPEC
879 CMP BYTE PTR [CHUCKENV
],0
881 MOV AX,DS ; XCHG ES,DS
886 JZ COPYCOMSP
; All set up for copy
891 MOV SI,OFFSET RESGROUP
:COMSPSTRING
903 MOV SI,CS:[ECOMLOC
] ;AC062
904 ADD SI,OFFSET RESGROUP
:PATHSTRING
910 mov es:comspec_print
,di ; Save ptr to beginning of comspec path
911 cmp byte ptr [si+1],':' ; Is there a drive specifier in comspec
912 jnz COPYCOMSPLOOP
; If not, do not skip over first 2 bytes
913 add es:comspec_print
,2
920 mov es:comspec_end
,di ; Save ptr to end of comspec path
924 mov es:cpdrv
,ah ; Load drive letter in comprmt2
925 assume
es:environment
927 call setup_for_messages
;AN060; set up parse and extended error messages
930 MOV BX,[RESMSGEND
] ;AC000; get end of resident
936 ; NOTE: The transient has to loaded directly after shrinking to the
938 ; There is an assumption made when loading the transient that it
939 ; still intact after the resident portion.
940 ; If any other ALLOC/DEALLOC/SETBLOCK operations are performed
941 ; inbetween, then there is a real good chance that the non-resident
942 ; portion will be overwritten by arena information.
945 INT int_command
; Shrink me to the resident only
947 ; Load in the transient and compute the checksum. We may do this in one of
948 ; two ways: First, cheat and use the transient loading code that exists in
949 ; the resident piece. This may be OK except that it will hit the disk.
951 ; But we do not need to hit the disk! The transient is already loaded but is
952 ; in the wrong place. We need to block transfer it up to the correct spot.
955 MOV TrnMvFlg
, 1 ; Indicate that transient has been moved
957 MOV SI,OFFSET RESGroup
:TranStart
960 MOV CX,OFFSET TRANGROUP
:TRANSPACEEND
962 ; We need to ensure that we do not have the potential of overwriting our
963 ; existing code in this move
964 ; It is OK to move if (SI+CX+Segment of Transient < TrnSeg).
967 mov ax,cx ; Get size of transient in bytes
968 add ax,si ; Calculate end of transient section
970 shr ax,cl ; Convert to paragraphs
971 inc ax ; Round up (for partial paragraph)
973 add ax,cx ; Add in current segment
974 cmp ax,Trnseg
; See if there is overlap
976 ; If we are too close to be safe, call LOADCOM instead of moving the code.
979 jmp short Trans_Loaded
982 ; Everything is set for an upward move. WRONG! We must move downward.
995 INVOKE CHKSUM
; Compute the checksum
996 MOV [SUM
],DX ; Save it
998 CMP BYTE PTR [PRDATTM
],0 ;eg
999 JNZ NOBATCHSEG
;eg Don't do AUTOEXEC or date time
1001 ; Allocate batch segment for D:/autoexec.bat + no arguments
1003 MOV BX,((SIZE BatchSegment
) + 15 + 1 + 0Fh)/16 ;eg
1006 JC NOBATCHSEG
;eg didn't allocate - pretend no batch
1007 MOV BATCH
,AX ;eg save batch segment
1010 MOV BX, 0FFFFH ; Get size of largest block for env
1014 ; Only allocate maximum 64K worth of environment
1016 SUB BX,TRNSIZE
;eg subtract # of transient paragraphs
1017 SUB BX,128 ;eg make sure we have 2K left
1019 CMP BX, 4096 ; 64K = 4096 paragraphs
1025 MOV AH, ALLOC
; Get max size
1028 mov bx,[envirseg
] ;g get old environment segment
1029 mov oldenv
,bx ;g save it
1030 mov usedenv
,0 ;g initialize env size counter
1037 MOV BX,EnvMax
; Copy over as much of the environment
1043 MOV EnvMax
, BX ; Convert EnvMax to bytes
1044 DEC BX ; Dec by one to leave room for double 0
1045 XOR DX,DX ; Use DX to indicate that there was
1046 ; no environment size error.
1049 CALL GetStrLen
; Get the size of the current env string
1050 push ds ;g get addressability to environment
1054 add usedenv
,cx ;g add the string length to env size
1057 CMP CX,1 ; End of environment was encountered.
1060 JAE OKCpyStr
; Can't fit in all of enviroment.
1061 INC DX ; Out of env space msg must be displayed
1070 OR DX,DX ; DX will be non-zero if error
1072 MOV DX,OUTENVERR_ptr
;AC000; get message number
1076 ; BX now has the left over size of the maximum environment
1077 ; We want to shrink the environment down to the minimum size
1078 ; Set the environment size to max(Envsiz,Env used)
1081 SUB CX, BX ; CX now has the environment used
1082 ADD CX, 16 ; Round up to next paragraph
1087 CMP CX, Envsiz
; Is environment used > Envsiz
1091 MOV BX, Envsiz
; Set environment to size needed
1092 mov ax,es ;eg get environment segment
1093 add ax,bx ;eg add number of environment paragraphs
1094 cmp ax,initend
;eg does this go past end of init?
1095 ja envsetok
;eg yes - do the setblock
1096 mov ax,es ;eg no - get back the environment segment
1097 mov bx,initend
;eg get the segment at end of init
1098 sub bx,ax ;eg setblock envir segment to end of init code
1099 mov resetenv
,1 ;eg set flag so we know to set envir later
1107 JNZ NOPHEAD
; Don't print header if SINGLECOM
1108 MOV DX,HEADER_ptr
;AC000; get message number
1113 CMP [BATCH
],0 ;eg did we set up a batch segment?
1114 JNZ dodate
;eg yes - go initialize it
1115 JMP NODTTM
; Don't do AUTOEXEC or date time
1117 ; Allocate batch segment for D:/autoexec.bat + no arguments
1120 MOV AX,BATCH
;eg get batch segment
1121 MOV EchoFlag
,3 ; set batch echo
1122 MOV NEST
,1 ; g set nest flag to 1 batch
1125 ; Initialize the segment
1130 MOV AL,1 ; G initialize echo for batch exit
1132 XOR AX,AX ; initialize to zero
1133 STOSW ; G batch segment of last job - batlast
1134 STOSW ; G segment for FOR
1136 STOSW ; position in file - batseek
1139 ; Clean out the parameters
1141 MOV AX,-1 ; initialize to no parameters
1145 ; Decide whether we should grab the default drive
1147 CMP BYTE PTR [AUTOBAT
],0
1150 MOV AH,GET_DEFAULT_DRIVE
1155 MOV [KAUTOBAT
],AL ;AN000; 3/3/KK
1159 ; Copy in the batch file name (including NUL)
1161 MOV SI,OFFSET RESGROUP
:AUTOBAT
1164 MOVSB ;AN027; move in carraige return to terminate string
1166 MOV DX,OFFSET RESGROUP
:AUTOBAT
1168 INT int_command
; See if AUTOEXEC.BAT exists
1173 JMP DRV0
;AC000; go process autoexec
1178 mov word ptr [triage_add
+2],ax
1182 jz AccDenErr
;AN000; was network access denied
1185 ; If AUTOEXEC.BAT is not found, then check for KAUTOEXE.BAT. Changed
1186 ; by Ellen to check only when in Korea. The country information
1187 ; returned will overlay the old parse data area, but we don't care
1188 ; since we won't need the parse information or country information.
1189 ; We only care about the country code returned in BX.
1191 MOV DX,OFFSET RESGROUP
:INTERNAT_INFO
;AN000; Set up internat vars
1192 MOV AX,INTERNATIONAL
SHL 8 ;AN000; get country dependent info
1194 JC NOKABAT
;AN000; Error - don't bother with it
1195 CMP BX,KOREA_COUNTRY_CODE
;AN000; Are we speaking Korean?
1196 JNZ OPENERR
;AN000; No, don't check for KAUTOEXE
1198 MOV DI, OFFSET BatFile
;AN000; 3/3/KK
1199 MOV SI,OFFSET RESGROUP
:KAUTOBAT
;AN000; Another trial to do 3/3/KK
1200 MOV CX,8 ;AN000; auto execution for the 3/3/KK
1201 REP MOVSW ;AN000; non-English country 3/3/KK
1202 MOVSB ;AN027; move in carraige return to terminate string
1203 MOV DX,OFFSET RESGROUP
:KAUTOBAT
;AN000; 3/3/KK
1204 MOV AX,OPEN
SHL 8 ;AN000; 3/3/KK
1205 INT int_command
;AN000; See if KAUTOEXE.BAT exists 3/3/KK
1206 JC NOKABAT
;AN000; 3/3/KK
1207 MOV BX,AX ;AN000; 3/3/KK
1208 MOV AH,CLOSE
;AN000; 3/3/KK
1209 INT int_command
;AN000; 3/3/KK
1210 JMP SHORT DRV0
;AN000; 3/3/KK
1212 NOKABAT: ;AN000; 3/3/KK
1213 call triage_add
;AN000; get extended error
1214 cmp ax, 65 ;AN000; network access denied?
1215 jnz openerr
;AN000; no - go deallocate batch
1217 AccDenErr: ;AN000; yes - put out message
1218 mov DX,ACCDEN
;AC000; get message number
1222 MOV ES,[BATCH
] ; Not found--turn off batch job
1225 MOV [BATCH
],0 ; AFTER DEALLOC in case of ^C
1227 mov nest
,0 ;g indicate no batch in progress
1230 MOV AX,OFFSET TRANGROUP
:DATINIT
1231 MOV WORD PTR[INITADD
],AX
1233 MOV WORD PTR[INITADD
+2],AX
1234 CALL DWORD PTR [INITADD
]
1240 JNZ DRV0
; Don't print header if SINGLECOM
1241 MOV DX,HEADER_ptr
;AC000; get message number
1245 DRV0: ; Reset APPEND state
1246 push ds ;AN042; save data segment
1247 push cs ;AN042; Get local segment into DS
1249 mov ax,AppendSetState
;AN042; Set the state of Append
1250 mov bx,Append_state
;AN042; back to the original state
1252 pop ds ;AN042; get data segment back
1253 JMP ENDINIT
;G Finish initializing
1256 ; Get length of string pointed to by DS:SI. Length includes NULL.
1257 ; Length is returned in CX
1268 ; If the transient has been loaded in TranSeg, then we need to use that
1269 ; segment for calls to routines in the transient area. Otherwise, the current
1270 ; code segment is used
1271 ; Segment returned in AX.
1275 cmp TrnMvFlg
, 1 ; Has transient portion been moved
1279 mov ax,OFFSET RESGroup
:TranStart
1291 PUSH DS ;AN000; save data and extra segment
1292 PUSH ES ;AN000; registers
1293 MOV AX,CS ;AN000; get local segment
1294 MOV ES,AX ;AN000; set ES and DS to point to it
1296 ;AD054; PUSH BX ;AC000; save BX register
1297 ;AD054; PUSH CX ;AC000; save CX register
1298 ;AD054; PUSH DX ;AC000; save DX register
1299 ;AD054; MOV AX,DX ;AC000; get message number
1300 ;AD054; MOV DH,DISP_CLASS ;AC000; get display class
1301 ;AD054; MOV DL,NO_CONT_FLAG ;AN000; set control flags off
1302 ;AD054; MOV BX,NO_HANDLE_OUT ;AC000; set message handler to use function 1-12
1303 ;AD054; XOR CH,CH ;AC000; clear upper part of cx
1304 ;AD054; MOV CL,NUMBER_SUBST ;AC000; set number of substitutions
1305 ;AD054; invoke SYSDISPMSG ;AC000; display the message
1306 ;AD054; MOV DISP_CLASS,UTIL_MSG_CLASS ;AC000; reset display class
1307 ;AD054; MOV NUMBER_SUBST,NO_SUBST ;AC000; reset number of substitutions
1308 ;AD054; POP DX ;AC000; restore registers
1309 ;AD054; POP CX ;AC000;
1310 ;AD054; POP BX ;AC000;
1311 invoke rprint
;AC054;
1333 CALL IFIND
; FIND THE NAME
1334 JC IFIND2
; CARRY MEANS NOT FOUND
1335 JMP ISCASB1
; SCAN FOR = SIGN
1337 ; On return of FIND1, ES:DI points to beginning of name
1341 CALL ICOUNT0
; CX = LENGTH OF NAME
1353 ;;;; IF KANJI 3/3/KK
1381 CALL ISCASB2
; SCAN FOR A NUL
1383 CMP BYTE PTR ES:[DI],0
1385 STC ; INDICATE NOT FOUND
1395 PUSH DI ; COUNT NUMBER OF CHARS UNTIL "="
1398 PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL
1408 MOV AL,equalsign
; SCAN FOR AN =
1412 XOR AL,AL ; SCAN FOR A NUL
1420 ; ****************************************************************
1422 ; * ROUTINE: IUPCONV (ADDED BY EMG 4.00)
1424 ; * FUNCTION: This routine returns the upper case equivalent of
1425 ; * the character in AL from the file upper case table
1426 ; * in DOS if character if above ascii 128, else
1427 ; * subtracts 20H if between "a" and "z".
1429 ; * INPUT: DS set to resident
1430 ; * AL char to be upper cased
1431 ; * FUCASE_ADDR set to the file upper case table
1433 ; * OUTPUT: AL upper cased character
1435 ; ****************************************************************
1437 assume
ds:resgroup
;AN000;
1439 iupconv proc
near ;AN000;
1441 cmp al,80h
;AN000; see if char is > ascii 128
1442 jb other_fucase
;AN000; no - upper case math
1443 sub al,80h
;AN000; only upper 128 chars in table
1446 lds bx,dword ptr fucase_addr
+1 ;AN000; get table address
1447 add bx,2 ;AN000; skip over first word
1448 xlat ds:byte ptr [bx] ;AN000; convert to upper case
1451 jmp short iupconv_end
;AN000; we finished - exit
1453 other_fucase: ;AN000;
1454 cmp al,lcasea
;AC000; if between "a" and "z",
1455 jb iupconv_end
;AC000; subtract 20h to get
1456 cmp al,lcasez
;AC000; upper case equivalent.
1457 ja iupconv_end
;AC000;
1458 sub al,20h
;AC000; Change lower-case to upper
1460 iupconv_end: ;AN000;
1463 iupconv endp
;AN000;
1465 init_contc_specialcase:
1466 ; This routine is called if control-C
1467 add sp,6 ; is type during the date/time prompt
1468 push si ; at initialization time. The desired
1469 mov si,dx ; response is to make it look like the
1470 mov word ptr [si+1],0d00h ; user typed <CR> by "popping" the
1471 pop si ; INT 21h stuff off the stack, putting
1472 iret ; a <CR> in the user's buffer, and
1473 ; returning directly to the user.
1474 ; In this case the user is TCODE.
1476 ; ****************************************************************
1478 ; * ROUTINE: GET_MSG_PTR
1480 ; * FUNCTION: Fill in translatable char table starting at
1481 ; * at Abort_char with translated characters.
1482 ; Set segments of resident messages.
1488 ; ****************************************************************
1490 CHAR_START EQU
201 ;AN000; first character translate is 1
1491 CHAR_END EQU
207 ;AN000; last is 6
1493 GET_MSG_PTR PROC
NEAR ;AN000;
1495 MOV AX,CHAR_START
;AN000; get first char translation
1496 MOV BX,OFFSET RESGROUP
:ABORT_CHAR
;AN000; get first char offset
1498 MOV DH,-1 ;AN000; utility message
1499 INVOKE SYSGETMSG
;AN000; get the offset of the char
1500 MOV CL,BYTE PTR [SI] ;AN000; get the character in CL
1501 MOV BYTE PTR [BX],CL ;AN000; put the character in the table
1502 INC BX ;AN000; point to next position in table
1503 INC AX ;AN000; increment message number
1504 CMP AX,CHAR_END
;AN000; are we at the end?
1505 JNZ MOVEMES
;AN000; no - keep loading
1507 MOV AX,DS ;AN000; get data segment
1508 MOV DRVNUM_OP_SEG
,AX ;AN000; set up segments for
1509 MOV DRVNUM_OP_SEG2
,AX ;AN000; message substitutions
1510 MOV DEVE_OP_SEG
,AX ;AN000; used in the resident
1511 MOV DEVE_OP_SEG2
,AX ;AN000; portion of command
1512 MOV ERR15_OP_SEG
,AX ;AN000; during initialization
1513 MOV ERR15_OP_SEG2
,AX ;AN000; to save resident
1514 MOV ERR15_OP_SEG3
,AX ;AN000; space.
1515 MOV BADFAT_OP_SEG
,AX ;AN000;
1516 MOV COMPRMT1_SEG
,AX ;AN000;
1517 MOV COMPRMT1_SEG2
,AX ;AN000;
1521 GET_MSG_PTR ENDP
;AN000;
1524 ; ****************************************************************
1526 ; * ROUTINE: Setup_for_messages
1528 ; * FUNCTION: Sets up system for PARSE and EXTENDED ERROR
1529 ; * messages as follows:
1531 ; * IF /P and /MSG are entered
1532 ; * keep PARSE and EXTENDED ERRORS in memory
1533 ; * ELSE IF /P is entered
1534 ; * use PARSE and EXTENDED ERRORS on disk
1535 ; * remove PARSE ERRORS from memory
1537 ; * remove PARSE ERRORS from memory
1540 ; * INPUT: PERMCOM Set up with user input
1541 ; * EXT_MSG Set up with user input
1542 ; * System set up to retain PARSE ERRORS
1544 ; * OUTPUT: registers unchanged
1546 ; ****************************************************************
1549 setup_for_messages proc
near ;AN060;
1551 push ds ;AN060; save data segment
1552 push es ;AN060; save environment segment
1556 mov ax,cs ;AN060; get local segment to ES and DS
1560 cmp [permcom
],0 ;AN060; was permcom set?
1561 jz no_permcom
;AN060; No - don't worry about messages
1562 cmp ext_msg
,set_extended_msg
;AN060; was /msg specified?
1563 jz permcom_slash_msg
;AN060; Yes - go process it
1565 mov ax,1 ;AN060; Set ES to 1 as a flag to the message
1566 mov es,ax ;AN060; services that messages are on disk
1567 mov di,offset resgroup
:extended_msg_start
-100h
;AN060; start address
1568 call set_ext_2f
;AN060; set extended error address
1569 mov di,offset resgroup
:parse_msg_start
-0100h ;AN060; start address
1570 call set_parse_2f
;AN060; set parse error address
1573 IFNDEF READ_DISK_INFO
;AN060;;
1574 Extrn READ_DISK_PROC
:Far ;AN060;;
1577 MOV AX,DOS_GET_EXT_PARSE_ADD
;AN060;; 2FH Interface
1578 MOV DL,DOS_SET_ADDR
;AN060;; Set the READ_DISK_PROC address
1579 LEA DI,READ_DISK_PROC
;AN060;;
1580 INT 2FH
;AN060;; Private interface
1581 jmp short permcom_end
;AN060; and exit
1583 permcom_slash_msg: ;AN060; Keep messages in memory
1584 mov di,offset resgroup
:extended_msg_start
;AN060; start address
1585 call set_ext_2f
;AN060; set the extended message address
1586 mov di,offset resgroup
:extmsgend
+15 ;AN060; get address of resident end
1587 mov [resmsgend
],di ;AN060; save it
1588 jmp short permcom_end
;AN060; exit
1591 cmp ext_msg
,set_extended_msg
;AN060; was /msg specified?
1592 jnz no_slash_msg
;AN060; no - no error
1593 mov disp_class
,parse_msg_class
;AN060; set up parse error msg class
1594 mov dx,LessArgs_Ptr
;AN060; get message number for "Required parameter missing"
1595 call print_message
;AN060; issue error message
1598 mov ax,(multdos
shl 8 or message_2f
);AN060; reset parse message pointers
1599 mov dl,set_parse_msg
;AN060; set up parse message address
1600 mov di,pars_msg_off
;AN060; old offset of parse messages
1601 mov es,pars_msg_seg
;AN060; old segment of parse messages
1602 int 2fh
;AN060; go set it
1605 call sysloadmsg
;AN060; load message addresses
1609 pop es ;AN060; get environment back
1614 setup_for_messages endp
;AN060;
1616 ; ****************************************************************
1618 ; * ROUTINE: Set_parse_2f
1620 ; * FUNCTION: Does the INT 2Fh to DOS to set the PARSE
1621 ; * message address that will later be retrieved
1622 ; * by the message services.
1624 ; * INPUT: ES set to segment of messages
1625 ; * DI points to offset of messages
1629 ; ****************************************************************
1631 Set_parse_2f proc
near ;AN060;
1633 mov ax,(multdos
shl 8 or message_2f
);AN060; set up to call DOS through int 2fh
1634 mov dl,set_parse_msg
;AN060; set up parse message address
1639 Set_parse_2f endp
;AN060;
1641 ; ****************************************************************
1643 ; * ROUTINE: Set_ext_2f
1645 ; * FUNCTION: Does the INT 2Fh to DOS to set the EXTENDED
1646 ; * message address that will later be retrieved
1647 ; * by the message services.
1649 ; * INPUT: ES set to segment of messages
1650 ; * DI points to offset of messages
1654 ; ****************************************************************
1656 Set_ext_2f proc
near ;AN060;
1658 mov ax,(multdos
shl 8 or message_2f
);AN060; set up to call DOS through int 2fh
1659 mov dl,set_extended_msg
;AN060; set up extended error message address
1664 Set_ext_2f endp
;AN060;
1667 ASSUME
DS:RESGROUP
, ES:RESGROUP
1672 INCLUDE SYSMSG
.INC ;AN000; include message services
1677 MSG_UTILNAME
<COMMAND
> ;AN000; define utility name
1679 MSG_SERVICES
<COMR
,NEARmsg
,LOADmsg
,NOCHECKSTDIN
,NOCHECKSTDOUT
> ;AC026; include message services macro