From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/CMD/APPEND/APPEND.ASM | 3462 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3462 insertions(+) create mode 100644 v4.0/src/CMD/APPEND/APPEND.ASM (limited to 'v4.0/src/CMD/APPEND/APPEND.ASM') diff --git a/v4.0/src/CMD/APPEND/APPEND.ASM b/v4.0/src/CMD/APPEND/APPEND.ASM new file mode 100644 index 0000000..5ca2b70 --- /dev/null +++ b/v4.0/src/CMD/APPEND/APPEND.ASM @@ -0,0 +1,3462 @@ +page 60,120 +; +.sall +title APPEND +include sysmsg.inc +msg_utilname +;----------------------------------------------------------------------------- +; +; Title: APPEND +; +; Author: G. G. A. Network version +; B. A. F.` DOS changes +; +; Syntax: From the DOS command line: +; +; APPEND [d:]path[[;[d:]path]...] +; - Used to specify the directories to be +; searched after the working directory. +; +; APPEND ; +; - Used to release all appended directories. +; +; APPEND +; - Used to show appended directories. +; +; First time only: +; +; APPEND [[d:]path | | /X | /E | /X /E] +; - [d:]path Normal support and Set path +; - Normal support +; - /X Extended support, SEARCH, FIND and EXEC +; - /E Use DOS Environment for path(s) +; +; Revision History: +; @@01 07/11/86 Fix hang in TopView start PTM P00000?? +; @@02 07/28/86 Fix APPEND size problem PTM P0000045 +; @@03 07/29/86 Fix APPEND status with /E problem PTM P00000?? +; @@04 07/30/86 Fix second APPEND hang PTM P0000053 +; @@05 08/13/86 Fix parameter error PTM P0000125 +; @@06 08/20/86 Fix APPEND xxx fails in TopView PTM P0000217 +; @@07 08/21/86 Resurrect APPEND version message PTM P0000252 +; @@08 08/21/86 APPEND=path first time hangs PTM P0000254 +; @@09 08/22/86 APPEND gets wrong path under nested COMMAND PTM P0000276 +; @@10 08/28/86 Change message for @@05 PTM P0000291 +; @@11 09/10/86 Support message profile and make +; msg length variable. R.G. PTM P0000479 +; @@12 09/25/86 Allow second external append call. (RG) PTM P0000515 +; @@13 09/30/86 APPEND gets wrong path under nested COMMAND PTM P0000600 +; Again. Fix in COMMAND now, so remove @@09 changes +; @@14 10/01/86 Lower case drive in path files PTM P0000600 +; @@15 10/06/86 Include "," and "=" in skip leading of +; argument area parsing. PTM P0000677 +; @@16 10/06/86 Fix not using full APPEND path PTM P0000794 +; @@17 12/03/86 When searching for "APPEND=" string in +; environment, make sure delimiter precedes.(RG) PTM P0000893 +; +;------------------------------------------------------------------- +; +; AN000 3.30 changes, GGA 6/87 new code. P000 +; AN001 Support DRIVE and PATH modes D043 +; AN002 Add truename function P1276 +; AN003 Add extended handle open function D250 +; AN005 +; AN006 Add DBCS support +; AN007 Release Environmental Vector space P2666 +; AN008 Allow equal symbol with append - APPEND=A:/1; P2901 +; AN009 Release Environmental Vector on only the P3333 +; first invocation of APPEND +; AN010 display invalid parm from command line P3908 +; +; +;----------------------------------------------------------------------------- +;Date Rev Comments +;----------------------------------------------------------------------------- +;06-02-86 0.0 Begin conversion to PC/DOS version +;06-20-86 0.0 End conversion to PC/DOS version +; +page + +cseg segment public para 'CODE' + assume cs:cseg + assume ds:nothing,es:nothing + +;----------------------------------------------------------------------------- +; Equates +;----------------------------------------------------------------------------- + +.xlist +;include fsi.lib +NETSYSUTIL EQU 0C2H ; SYSTEM UTILITIES +NETENQ EQU 07H ; ENQ RESOURCE +NETDEQ EQU 08H ; DEQ RESOURCE +;include task.lib +TCBR_APPEND EQU 001H ; APPEND ACTIVE +;include DOS.lib +DOSSERVER EQU 5DH ; SERVER OPERATION +DOSSETERROR EQU 0AH ; SET EXTENDED ERROR +;include server.lib +DPL STRUC +DPL_AX DW 0 ;AX REG +DPL_BX DW 0 ;BX REG +DPL_CX DW 0 ;CX REG +DPL_DX DW 0 ;DX REG +DPL_SI DW 0 ;SI REG +DPL_DI DW 0 ;DI REG +DPL_DS DW 0 ;DS REG +DPL_ES DW 0 ;ES REG +DPL_XID DW 0 ;RESERVED +DPL_UID DW 0 ;SERVER USER ID +DPL_PID DW 0 ;REDIRECTOR PROCESS ID +DPL ENDS +include sysmac.lib +include versiona.inc +include appendp.inc ; parseing stuff for append ;AN004; +.list +; extrn end_address:near ; end of stay resident stuff + +; extrn bad_append_msg:byte ; messages +; extrn path_error_msg:byte +; extrn parm_error_msg:byte +; extrn path_parm_error_msg:byte +; extrn no_append_msg:byte ; @@05 +; extrn append_assign_msg:byte +; extrn append_TV_msg:byte ; @@01 +; extrn bad_DOS_msg:byte +; extrn second_APPEND_msg:byte ; @@04 + +; extrn len_bad_append_msg:word ;@@11 +; extrn len_path_error_msg:word ;@@11 +; extrn len_parm_error_msg:word ;@@11 +; extrn len_path_parm_error_msg:word ;@@11 +; extrn len_no_append_msg:word ;@@11 +; extrn len_append_assign_msg:word ;@@11 +; extrn len_append_TV_msg:word ;@@11 +; extrn len_bad_DOS_msg:word ;@@11 +; extrn len_second_APPEND_msg:word ;@@11 + +; Environmental Vector + +PSP_Env equ 2ch ;Environmental vector segment in PSP ;an007; dms; + +; Interrupts + +DOS_function equ 21h ; DOS function call interrupt +int_function equ 2fh ; DOS internal function interrupt, used + ; to verify APPEND presence +termpgm equ 20h ; @@05 +resident equ 27h + +; Function calls + +get_vector equ 3521h ; DOS function call to get INT 21 vector +set_vector equ 2521h ; DOS function call to set INT 21 vector +get_intfcn equ 352fh ; DOS function call to get INT 2f vector +set_intfcn equ 252fh ; DOS function call to set INT 2f vector +get_version equ 30h ; DOS function call to get DOS version number +get_DTA equ 2fh ; DOS function get DTA +set_DTA equ 1ah ; DOS function set DTA +get_crit_err equ 3524h ; DOS function call to get INT 24 vector +set_crit_err equ 2524h ; DOS function call to set INT 24 vector +get_PSP equ 62h ; DOS function call to get PSP address +Free_Alloc_Mem equ 49h ; DOS function call to free alloc. mem. ;an007; dms; + +print_string equ 09h ; DOS function call to get print a string +ctrl_break equ 33h ; DOS function call to get/set ctrl-break + +awrite equ 40h ; write function +get_dir equ 47h ; get current dir +change_dir equ 3bh ; change dir +get_disk equ 19h ; get current disk +change_disk equ 0eh ; change disk +term_stay equ 31h ; terminate a process and stay resident +term_proc equ 4ch ; terminate a process + +redir_flag equ 0000000000001000B ; redir flag for net installation check + +; DOS INT 2f function for APPEND presence + +append_2f equ 0b7h ; int 2f function code for append +applic_2f equ 0aeh ; int 2f function code for applications +COMMAND_2f equ -1 ; int 2f subfunction code for COMMAND call +append_inst equ 0ffh ; flag means append is there + +; INT 2f sub-function codes ;AN000; + +are_you_there equ 0 ; function code for presence check +old_dir_ptr equ 1 ; means APPEND 1.0 is trying to run +get_app_version equ 2 ; fun code for get ver request +tv_vector equ 3 ; fun code for set TV vector +dir_ptr equ 4 ; function code to return dirlist ptr +get_state equ 6 ; function code to return append ;AN001; + ; state ;AN001; +set_state equ 7 ; function code to set append ;AN001; + ; state ;AN001; + +DOS_version equ 10h ; function call to get DOS version +true_name equ 11h ; one-shot truename fcn for ASCIIZ ops ;AN002; + +; DOS INT 21 function calls that APPEND traps + +FCB_opn equ 0fh +file_sz equ 23h +handle_opn equ 3dh +dat_tim equ 57h +FCB_sch1 equ 11h +handle_fnd1 equ 4eh +exec_proc equ 4bh +ext_handle_opn equ 6ch ;AN003; + +break macro ; this is a dummy break macro so PDB.INC + endm ; won't blow up in the build + +; define some things for PDB (PSP) ;AN002; + ;AN002; +include pdb.inc ;AN002; + ;AN002; +true_name_flag equ 01h ; flag for true name function ;AN002; +eo_create equ 00f0h ; mask to check extended opens for create ;AN003; + +; Error codes that don't mean stop looking + +FCB_failed equ 0ffh ; FCB open failed +FCB_file_not_found equ 2 ; file not found on FCB open +handle_file_not_found equ 2 ; file not found on handle open +handle_path_not_found equ 3 ; path not found on handle open +FCB_no_more_files equ 18 ; no more matching files +handle_no_more_files equ 18 ; no more matching files + +; Equates for TOPVIEW barrier +TV_TRUE equ -1 ; this was changed from TRUE ;AN000; + ; because 3.30 parser uses TRUE ;AN000; +false equ 0 ; + +; Message equates + +tab_char equ 9 +cr equ 13 +lf equ 10 +beep equ 7 +STDOUT equ 0001h ; standard output file +STDERR equ 0002h ; standard error file +null equ 0 + +page + +;----------------------------------------------------------------------------- +; Resident data area +;----------------------------------------------------------------------------- + +version_loc: ; version number + db major_version,minor_version +; dw message_list ; pointer to message table + + even +vector_offset dw 0 ; save pointer to old int 21 here +vector_segment dw 0 +crit_vector_offset dw 0 ; save pointer to old int 24 here +crit_vector_segment dw 0 +intfcn_offset dw 0 ; save pointer to old int 2f here +intfcn_segment dw 0 +dirlst_offset dw 0 ; save pointer to dir list here +dirlst_segment dw 0 +tv_vec_off dw 0 ; save TV vector here +tv_vec_seg dw 0 + +pars_off dd cseg: SysParse ; save pointer to parser here +;pars_off dw offset SysParse ; save pointer to parser here +;pars_seg dw 0 + +app_dirs_seg dw 0 ; save ES here during FCB + +FCB_ptr dd 0 ; save pointer to FCB here +handle_ptr dd 0 ; save pointer to ASCIIZ string here + +stack_offset dw 0 +stack_segment dw 0 ; Calling process stack + +incoming_AX dw 0 ; AX saved at entry to interrupt handler +incoming_CX dw 0 ; CX saved at entry to interrupt handler +; must be together +incoming_BX dw 0 ; BX saved at entry to interrupt handler +incoming_ES dw 0 ; ES saved at entry to interrupt handler +; must be together +ax_after_21 dw 0 ; AX saved after call to real INT 21 +; temp_DS_save dw 0 ; DS saved during stack ops +temp_CS_save dw 0 ; CS saved during stack ops (set_return_flags) +temp_IP_save dw 0 ; IP saved during stack ops (set_return_flags) +FCB_drive_id db 0 ; save the drive id for FCB opens here + +;------------------------ +; DBCS stuff here ;AN006; + ;AN006; +DBCSEV_OFF DW 0 ; OFFSET OF DBCS EV ;AN006; +DBCSEV_SEG DW 0 ; SEGMENT OF DBCS EV ;AN006; + ;AN006; +;DEFAULT DBCS ENVIRONMENTAL VECTOR ;AN006; +EVEV DB 00H,00H ;AN006; + DB 00H,00H ;AN006; + DB 00H,00H ;AN006; + ;AN006; +dbcs_fb dw 0 ; offset of DBCS first byte chars found +;------------------------ + +initial_pass dw 0 ; flag used to indicate inital APPEND ;AN007; + +incoming_DX dw 0 ; used for saves for extended open ;AN003; +incoming_SI dw 0 ; used for saves for extended open ;AN003; +incoming_DI dw 0 ; used for saves for extended open ;AN003; +incoming_DS dw 0 ; used for saves for extended open ;AN003; +true_name_count dw 0 ; used to save number of chars in true_name dir ;AN003; + +int_save_ip dw 0 ; save registers here during critical +int_save_cs dw 0 ; error handler stack ops + +work_disk db "?:\" ; user's working disk +work_dir db 64 dup(" ") ; user's working dir +app_disk db "?:\" ; user's working disk +app_dir db 64 dup(" ") ; user's append disk's working dir +ctrl_break_state db 0 ; save the old ctrl-break state here + +end_search db 0 ; end search flag +try_dir db 128 dup (0) ; try this dir +fname db 15 dup (0) ; 8.3 filename stripped from original + ; ASCIIZ string +app_dirs_ptr dw 0 ; pointer to appended dir to try + +set_name db "SET " ; SET command +; must be together +setappend_name db "SET " ; SET command +append_id db "APPEND=" ; display from here for user +; must be together +app_dirs db ";" + db 128 dup (0) ; area for storing appended dirs + db 0 ; just to insure that the last dir is null terminated +semicolon db ";",0 ; null list + +; Flags / barriers added for TopView + +tv_flag db 0 ; flag to indicate re-entr from TopView + +parse_flag db 0 ; flag used by APPEND parsing + +FCB_ext_err db 0 ; flag used to indicate that FCB + ; open failed and ext err was done +crit_err_flag db 0 ; flag used to indicate that a critical + ; error happened +ext_err_flag db 0 ; flag used to indicate that ext err + ; must be set 0 = don't set, 1 = do set +in_middle db 0 ; flag used to tell if we made it to + ; middle of string before finding a space +equal_found db 0 ; multiple = check +;crit_sect_flag db 0 ; critical section flag + +stack_area dw 99 dup(0) ; stack area for append +append_stack dw 0 + +net_config dw 0 ; flag word for what (if any) network + ; config we are running under + ; as long as this word is zero, a clear determination + ; has not been made about the configuration + + even +ext_err_dpl DPL <> ; reserve a DPL for get/set extended error code + + +save_ext_err DPL <> ; reserve a DPL for first extended + ; error code + +;------------------------------------------------------------------- ;AN001; +; ;AN001; +; mode_flags This status word is used to control the various ;AN001; +; APPEND functions and modes. ;AN001; +; ;AN001; +;------------------------------------------------------------------- ;AN001; +mode_flags dw Path_mode + Drive_mode + Enabled ;AN001; + ; mode control flags ;AN001; + ; initially - path, drive and ;AN001; + ; enabled ;AN001; + +; equates for mode_flags follow: ;AN001; + +X_mode equ 8000h ; in /X mode +E_mode equ 4000h ; in /E mode +Path_mode equ 2000h ; PATH in string OK ;AN001; +Drive_mode equ 1000h ; DRIVE in string OK ;AN001; +Enabled equ 0001h ; APPEND enabled ;AN001; + +;------------------------------------------------------------------- + +cmd_name@ dd ? ; internal name string + +expected_error dw ? ; error to do append scan +expected_ext_error dw ? ; error to do append scan + +cmd_env dw ? ; pointer to COMMANDs environment +cmd_buf dw ? ; CMDBUF offset (in SS) + +incoming_DTA dd ? ; user's DTA (on EXEC) +exec_DTA db 21+1+2+2+2+2+13 dup(0) ; find DTA for exec emulation + +old_syntax db 0 ; using network syntax + +res_append db 0 ; resident append call ; @@05 + +abort_sp dw ? ; sp to restore on errors ; @@05 + +crlf label byte + db CR,LF +crlf_len equ $ - crlf + +;******************************************************************* ;an010;bgb +; parser message display area ;an010;bgb +;******************************************************************* ;an010;bgb +inv_parm db 0bh ;length ;an010;bgb + db 0 ;reserved ;an010;bgb +si_off dw 0 ;put offset of command line here ;an010;bgb +si_seg dw 0 ;put segment of command line here ;an010;bgb + db 0 ;use percent zero ;an010;bgb + db Left_Align+Char_Field_ASCIIZ ;type of data ;an010;bgb + db 128 ;max width ;an010;bgb + db 1 ;min width ;an010;bgb + db ' ' ;pad char ;an010;bgb + +;------------------------------------------------------------------- +; +; resident message area +; +;------------------------------------------------------------------- + +MSG_SERVICES +MSG_SERVICES ;an010;bgb +MSG_SERVICES + +.xlist +;----------------------------------------------------------------------------- +; macros +;----------------------------------------------------------------------------- + +;----------------------------- +; save and restore register macros +save_regs macro + push bx + push cx + push dx + + push di + push si + push ds + push es + endm + +restore_regs macro + pop es + pop ds + pop si + pop di + + pop dx + pop cx + pop bx + endm + +;----------------------------- +; this macro is used instead of the normal POPF instruction to help +; prevent a 286 bug from occurring +popff macro + local myret + jmp $+3 +myret label near + iret + push cs + call myret + endm + +;----------------------------- ; @@12 +; check character ; @@12 +; ; @@12 +chkchar macro char ; @@12 + lodsb ; @@12 + and al,0dfh ; @@12 + cmp al,char ; @@12 + jne ccn_ret ; @@12 + endm ; @@12 +.list + +page +;----------------------------------------------------------------------------- +; resident routine - control transferred here on INT 21 +; check to see if this call has a function code we are interested in +;----------------------------------------------------------------------------- + + +tv_entry: + pushf ; @@01 + jmp check_fcb_open ; @@01 + +interrupt_hook: +resident_routine: + pushf ; save the user's flags (old stack) + + cmp tv_flag,TV_TRUE ; see if in TV ;AN000; + je use_old ; yes, old_vect + +check_fcb_open: ; @@01 + +;------------------------------------------------------------------- ;AN001; +; first, check to see if APPEND disabled, if so, skip everything ;AN001; +; and go to real INT 21 handler ;AN001; +;------------------------------------------------------------------- ;AN001; + test mode_flags,Enabled ; APPEND disabled? ;AN001; + jz real_jump ; yes, skip all other checks ;AN001; + + cmp ah,FCB_opn ; FCB open? + jump E,FCB_open ; yes, do the APPEND + + cmp ah,handle_opn ; handle open? + jump E,handle_open ; yes, do the APPEND + + cmp ah,ext_handle_opn ; extended handle open? ;AN003; + jump E,ext_handle_open ; yes, do the APPEND ;AN003; + ;AN003; + cmp ah,file_sz ; file size? + jump E,FCB_open ; yes, do the APPEND + + + test mode_flags,X_mode ; /X mode not selected + jz real_jump + + cmp ah,FCB_sch1 ; search? + jump E,FCB_search1 ; yes, do the APPEND + + cmp ah,handle_fnd1 ; find? + jump E,handle_find1 ; yes, do the APPEND + + cmp tv_flag,TV_TRUE ; cant do in TopView ;AN000; + je skip_exec + cmp ax,exec_proc*256+0 ; EXEC? + jump E,exec_pgm ; yes, do the APPEND +skip_exec: + cmp ax,exec_proc*256+3 ; EXEC? + jump E,exec_pgm ; yes, do the APPEND + + page +;----------------------------------------------------------------------------- +; By here, we know that the call was not one we are interested in, +; pass through to old INT 21. +; Since this is done with a jmp, control will pass back to original caller +; after DOS is finished. +;----------------------------------------------------------------------------- + +real_jump: + cmp tv_flag,TV_TRUE ; see if called by TV ;AN000; + jne use_old ; yes, use old vect + + popff ; restore user's flags + jmp dword ptr tv_vec_off ; pass through to TV + +use_old: + popff ; restore user's flags (old stack) + jmp dword ptr Vector_Offset ; jump to old INT 21 + +page +;----------------------------------------------------------------------------- +; FCB_search1 - this routine handles FCB search first calls +;----------------------------------------------------------------------------- + +FCB_search1: + mov expected_ext_error,fcb_no_more_files + jmp short FCB_openx1 + +;----------------------------------------------------------------------------- +; FCB_open - this routine handles FCB open calls +;----------------------------------------------------------------------------- + +FCB_open: + mov expected_ext_error,fcb_file_not_found +FCB_openx1: + call check_config ; check the config flags + call crit_sect_set ; set critical section flag + + call tv_barrier + + mov incoming_AX,ax ; save user's AX + mov word ptr FCB_ptr+0,dx ; save FCB pointer + mov word ptr FCB_ptr+2,ds + + popff ; restore user's flags + call int_21 ; try the open + + cli + mov AX_after_21,ax ; save AX as it came back from INT + pushf ; save flags from operation + cmp al,FCB_failed ; open failed ? + je check_error ; yes, lets check extended error + jmp set_return_flags ; no, fix the stack, then ret to caller + +check_error: + call get_ext_err_code ; get the extended error code + mov FCB_ext_err,1 ; set FCB ext error + call save_first_ext_err ; save first extended error code + mov ax,ext_err_dpl.DPL_AX ; get error in ax + cmp ax,expected_ext_error ; file not found? + je FCB_openx2 ; yes, lets look around for file + lea dx,save_ext_err ; + call set_ext_err_code ; set the extended error code + jmp set_return_flags ; no, fix the stack, then return + +FCB_openx2: + +; set up APPEND's stack + + popff ; get rid of the flags from the + ; real operation +; mov temp_DS_save,ds ; Save DS reg + mov stack_segment,ss ; Save it + mov stack_offset,sp ; Save it + mov ax,cs ; Get current segment + mov ss,ax ; and point stack seg here + lea sp,append_stack ; set up new stack + + save_regs ; save registers + + push cs ; establish addressability + pop ds + + call ctrl_break_set ; set ctrl-break handler + call crit_err_set ; set crit err handler + + mov ext_err_flag,1 ; flag for setting critical error + +; fix FCB drive spec + + les bx,dword ptr FCB_ptr ; ES:BX points to FCB + mov ah,ES:byte ptr [bx] ; get FCB drive spec + cmp ah,-1 ; extended FCB? + jne not_ext_FCB1 + add bx,1+5+1 ; point to real drive letter + mov ah,ES:byte ptr [bx] ; get FCB drive spec + +not_ext_FCB1: + mov FCB_drive_id,ah ; save it for later + mov ES:byte ptr [bx],0 ; zero the drive field out to + ; use default drive + + mov ah,get_disk ; get disk + call int_21 ; call DOS INT 21 handler + + add al,"A" ; make it a character + mov work_disk,al ; save it + + mov ah,get_dir ; get directory + xor dx,dx ; default drive + lea si,work_dir ; save area + call int_21 ; call DOS INT 21 handler + + call address_path ; get address of path + cmp es: byte ptr [di],";" ; is the append list null? + jump E,null_list ; exit append + mov app_dirs_seg,es ; save app dirs segment + mov si,di ; source + +try_another1: + lea di,try_dir ; destination + call get_app_dir ; copy dir to try into try_dir + mov app_dirs_ptr,si ; save updated pointer + + +;----------------------------- +try_app_dir1: + mov app_disk,0 ; zero for current dir + cmp try_dir+1,":" ; see if we have a drive + jne no_drive ; char should be a colon + +; yes, there was a drive specified, must do the change disk function call + + mov ah,change_disk ; change disk + mov dl,try_dir ; get the char representation of the drive + mov app_disk,dl ; save it away for later use + call cap_dl + sub dl,"A" ; convert from char to drive spec + call int_21 ; call DOS INT 21 handler +; jc check_end_dir_list ; there was an error, see if there is + ; another to try + + cmp crit_err_flag,0 ; did we experience a critical error + jne set_err_code ; yes, fake a file_not_found + +no_drive: + mov ah,get_dir ; get directory + xor dx,dx ; default drive + lea si,app_dir ; save area + call int_21 ; call DOS INT 21 handler + +; check to see if there was a critical error + + cmp crit_err_flag,0 ; did we experience a critical error + je cd_worked ; no, the cd worked + jmp short set_err_code + +save_regs_and_set: + pushf ; save everything again + save_regs + push cs ; re-establish addressability + pop ds ; ds = cs + +set_err_code: + xor ah,ah ; make ax look like open failed + mov al,FCB_failed + mov ax_after_21,ax ; save it away so we can restore it below + + jmp no_more_to_try + +cd_worked: + lea dx,try_dir ; point dx to dir to try + mov ah,change_dir ; change dir to appended directory + call int_21 ; call DOS INT 21 handler + +; try the open in this dir + + restore_regs ; make regs look like when user + mov ax,incoming_AX ; called us + + call int_21 ; call DOS INT 21 handler + mov ax_after_21,ax ; save AX + cmp crit_err_flag,0 ; did we get critical error? + jne save_regs_and_set ; yes, fake a file_not_found + cmp al,FCB_failed ; did open work? + jne open_ok + call get_ext_err_code ; get the extended error code + +open_ok: + pushf ; save everything again + save_regs + + push cs ; re-establish addressability + pop ds ; ds = cs + +; restore user's working disk and restore the dir on the appended drive + + mov ah,change_disk ; change disk back to our original + mov dl,work_disk + call cap_dl + sub dl,"A" ; convert from char to drive spec + call int_21 ; call DOS INT 21 handler + + mov ah,change_dir ; change dir + lea dx,app_disk ; save area (this time include drive) + call int_21 ; call DOS INT 21 handler + +; this is for ..\dirname ptr + + mov ah,change_dir ; change dir + lea dx,work_disk ; save area (this time include drive) + call int_21 ; call DOS INT 21 handler + + mov ax,ax_after_21 ; restore AX + cmp al,FCB_failed ; did open work? + jne FCB_open_worked + mov ax,ext_err_dpl.DPL_AX + cmp ax,expected_ext_error + jne no_more_to_try ; not file not found + +check_end_dir_list: + mov es,app_dirs_seg ; restore es + mov si,app_dirs_ptr + cmp si,null ; should we try again? + je no_more_to_try ; no + jmp try_another1 ; yes + +FCB_open_worked: + mov byte ptr ext_err_flag,0 ; the open worked, no need to set ext err code + jmp short set_disk + +no_more_to_try: +; restore user's working disk and dir + +; The following code up to label "null_list" which +; restores the user's drive and path was moved in front +; of the code to restore the drive spec in FCB. +; + mov ah,change_disk ; change disk + mov dl,work_disk + call cap_dl + sub dl,"A" ; convert from char to drive spec + call int_21 ; call DOS INT 21 handler + + mov ah,change_dir ; change dir + lea dx,work_disk ; save area (this time include drive) + call int_21 ; call DOS INT 21 handler + +null_list: + mov ah,FCB_drive_id ; get FCB drive spec +; cmp ah,0 ; did they ask for default drive? +; je fix_drive_spec ; yes, leave it alone + jmp short fix_drive_spec + +set_disk: ; set drive number in FCB + mov ah,work_disk ; no, give them the found drive spec + sub ah,"A"-1 ; convert from char to drive spec + +; ah has proper drive spec to put into FCB, do it + +fix_drive_spec: + les bx,dword ptr FCB_ptr ; ES:BX points to FCB + cmp ES:byte ptr[bx],-1 ; extended FCB + jne not_ext_FCB2 ; put in the proper drive spec + add bx,1+5+1 ; point to real drive letter + +not_ext_FCB2: + mov ES:byte ptr [bx],ah + + + call ctrl_break_restore + call crit_err_restore + +; find out if there is a need to set the extended error code + + cmp ext_err_flag,0 ; do we need to set the extended error code? + je no_ext_err ; no, finish up + lea dx,ext_err_dpl + cmp FCB_ext_err,0 + je handle_ext_err + lea dx,save_ext_err + +handle_ext_err: + call set_ext_err_code ; yes, go set the ext error info + +; all done with append, clean things back up for the user + +no_ext_err: + restore_regs ; restore registers + + jmp reset_stack ; fix stack, ret to caller +page + +;----------------------------------------------------------------------------- +; handle_find - APPEND handle find function +;----------------------------------------------------------------------------- + +handle_find1: + mov incoming_CX,cx ; save user's CX + mov expected_error,handle_no_more_files +; mov expected_ext_error,handle_no_more_files + jmp short handle_openx + +;----------------------------------------------------------------------------- +; exec_pgm - APPEND exec program function +;----------------------------------------------------------------------------- + +exec_pgm: + mov incoming_BX,bx ; save user's ES:BX + mov incoming_ES,es + mov expected_error,handle_file_not_found +; mov expected_ext_error,handle_no_more_files + jmp short handle_openx + +;----------------------------------------------------------------------------- ;AN003; +; ext_handle_open - APPEND extended handle open function ;AN003; +;----------------------------------------------------------------------------- ;AN003; +ext_handle_open: ;AN003; + test dx,eo_create ; does this call specify create? ;AN003; + jz no_eo_create ; no, we can continue ;AN003; + ;AN003; + jmp real_jump ; yes, do nothing but pass on to real ;AN003; + ; INT 21 handler ;AN003; + ;AN003; +; getting here means the caller did not specify the create option ;AN003; + ;AN003; +no_eo_create: ;AN003; + ;AN003; + mov incoming_BX,bx ; save user's registers ;AN003; + mov incoming_CX,cx ; extended open sure does use a lot ;AN003; + mov incoming_DX,dx ; of registers ;AN003; + mov incoming_SI,si ;AN003; + mov incoming_DI,di ;AN003; + mov incoming_ES,es ;AN003; + mov incoming_DS,ds ;AN003; + ;AN003; + mov expected_error,handle_file_not_found ;AN003; + jmp short handle_openx ; for now ... ;AN003; + ;AN003; +;----------------------------------------------------------------------------- +; handle_open - APPEND handle open function +;----------------------------------------------------------------------------- + +handle_open: + mov expected_error,handle_file_not_found +; mov expected_ext_error,handle_file_not_found + +handle_openx: + call check_config ; check the config flags + call crit_sect_set ; set critical section flag + + call tv_barrier ; no op on exec + + mov incoming_AX,ax ; save user's AX + mov word ptr handle_ptr+0,dx ; save path pointer + mov word ptr handle_ptr+2,ds + + popff ; restore user's flags + call int_21 ; try the open + + cli + mov AX_after_21,ax ; save AX as it came back from INT + pushf ; save flags from operation + +; find out if we had an error, and if so was it the one we were +; looking for + + jc what_happened ; yes, lets find out what happened + mov incoming_AX,-1 ; insure no exec done later + jmp set_return_flags ; no, fix the stack, then ret to caller + ; this means that the real call worked, + ; APPEND does not need to do anything + +what_happened: +; cmp ax,handle_path_not_found ; normal errors +; je handle_search ; yes, look for the file + cmp ax,expected_error ; was the error file not found? + je handle_search ; yes, look for the file + jmp set_return_flags ; no, fix the stack, then ret to caller + + +handle_search: + call get_ext_err_code ; get the extended error code information + +; set up APPEND's stack + popff ; get rid of the flags from the + ; real operation +; mov temp_DS_save,ds ; Save DS reg + mov stack_segment,ss ; Save it + mov stack_offset,sp ; Save it + mov ax,cs ; Get current segment + mov ss,ax ; and point stack seg here + lea sp,append_stack ; set up new stack + + save_regs ; save registers + pushf ; + push cs ; establish addressability + pop ds + + call crit_err_set + + call ctrl_break_set + +; all done with the prep stuff, let's get down to business + +;------------------------------------------------------------------- ;AN001; +; ;AN001; +; before doing anything else, check DRIVE and PATH modes ;AN001; +; ;AN001; +;------------------------------------------------------------------- ;AN001; +; ;AN001; + + pushf ; save flags ;AN001; + push ax ; save AX ;AN001; + ;AN001; + cmp incoming_AX,exec_proc*256 ; is this call an exec? + je drive_and_path_ok + + +;------------------------------------------------------------------- +; Set up ES:SI to point to incoming string +;------------------------------------------------------------------- + + cmp incoming_AX,ext_handle_opn*256+0 ;is this call an ext open? ;AN003; + jne no_eo13 ;AN003; + mov si,incoming_SI ; DS:SI points to original name for ex open ;AN003; + mov es,incoming_DS ; but this code wants ES:SI to point to it ;AN003; + lea di,fname ; DS:DI points to fname area ;AN003; + jmp eo_skip3 ; skip the old stuff ;AN003; + ;AN003; +no_eo13: ;AN003; + les si,dword ptr handle_ptr ; ES:SI points to original handle + lea di,fname ; DS:DI points to fname area +eo_skip3: +;------------------------------------------------------------------- + + test mode_flags,Drive_mode ; Drive_mode enabled? + jnz check_path_mode ; yes, go check path mode + + call check_for_drive ; no, find out if there is a drive + ; specified + cmp ax,0 ; was there a drive letter? + je check_path_mode ; no, go check path mode + +;------------------------------------------------------------------- +; getting here means that Drive_mode is disabled and that a drive letter +; was found. This means we give up on this APPEND operation + + jmp drive_or_path_conflict + + +check_path_mode: + test mode_flags,Path_mode ; Path_mode enabled? + jnz drive_and_path_ok ; yes, go do the APPEND function + + call check_for_path ; no, find out if there is a path + ; specified + + cmp ax,0 ; was there a path? + jne drive_or_path_conflict ; no, go do the APPEND function + + + call check_for_drive ; no, find out if there is a drive + ; specified + cmp ax,0 ; was there a drive letter? + je drive_and_path_ok ; no, everything is OK + ; yes, fall through and exit w/error + +;------------------------------------------------------------------- ;AN001; +; getting here means that Drive_mode is disabled and that a drive ;AN001; +; letter was found. This means we give up on this APPEND operatio ;AN001; n + +drive_or_path_conflict: + + pop ax ; clean up stack + popff + +; restore_regs ; restore some regs ;AN002; +; pop ax + + mov ext_err_flag,1 ; we need to set extended error info + mov ax,expected_error ; make ax look like we got file not found + mov ax_after_21,ax ; save it away so we can restore it below + popff ; get flags from stack + stc ; set the carry flag + pushf ; put 'em back + + jmp no_more_to_try2 + + +drive_and_path_ok: ;AN001; + pop ax ; restore AX ;AN001; + popff ; restore flags ;AN001; + ;AN001; +;------------------------------------------------------------------- ;AN001; +; end of code to check DRIVE and PATH modes ;AN001; +;------------------------------------------------------------------- ;AN001; + + cmp incoming_AX,ext_handle_opn*256+0 ;is this call an ext open? ;AN003; + jne no_eo1 ;AN003; + mov si,incoming_SI ; DS:SI points to original name for ex open ;AN003; + mov es,incoming_DS ; but this code wants ES:SI to point to it ;AN003; + lea di,fname ; DS:DI points to fname area ;AN003; + jmp eo_skip1 ; skip the old stuff ;AN003; + ;AN003; +no_eo1: ;AN003; + les si,dword ptr handle_ptr ; ES:SI points to original handle + lea di,fname ; DS:DI points to fname area +eo_skip1: ;AN003; + call get_fname ; strip just the 8.3 filename from + ; the original ASCIIZ string + call address_path ; address the path + cmp es: byte ptr [di],";" ; is append list null ? + jump E,no_more_to_try2 ; exit append + popff ; + mov si,di ; pointer to list of appended directories + pushf ; push flags onto stack just for the + ; popff below + +try_another2: + popff + lea di,try_dir ; buffer to be filled with dir name + ; to try + push cx ; save CX + call get_app_dir ; this routine will return with a dir + ; to try in try_dir + mov true_name_count,cx ; save number of chars for later us ;AN003; + pop cx + mov app_dirs_ptr,si ; save updated pointer + + +;----------------------------- +try_app_dir2: + + call append_fname ; glue the filename onto the end of the dir to try + + +; we now have an ASCIIZ string that includes the original 8.3 filename +; and one of the appended dir paths + + mov ax,incoming_AX + mov cx,incoming_CX + lea dx,try_dir ; point to new ASCIIZ string + + cmp incoming_AX,ext_handle_opn*256+0 ; extended open? ;AN003; + jne not_eo1 ;AN003; + ;AN003; +; this is an extended open call ;AN003; + ;AN003; + save_regs ;AN003; + ;AN003; + mov si,dx ; ext open wants DS:SI -> filename ;AN003; + push cs ;AN003; + pop ds ;AN003; + ;AN003; + mov ax,incoming_AX ; function code ;AN003; + mov bx,incoming_BX ; mode word ;AN003; + mov cx,incoming_CX ; attributes ;AN003; + mov dx,incoming_DX ; flags ;AN003; + mov es,incoming_ES ; ES:DI parm_list pointer ;AN003; + mov di,incoming_DI ;AN003; + ;AN003; + call int_21 ; try the extended open ;AN003; + ;AN003; + restore_regs ;AN003; + pushf ; save flags ;AN003; +; mov es,incoming_ES ; restore es as it was ;AN003; + jmp not_exec2 ; go find out what happened ;AN003; + ;AN003; + ;AN003; +not_eo1: ;AN003; + cmp incoming_AX,exec_proc*256+0 ; exec pgm call + jne not_exec1 + +; this is an exec call ;AN003; + + push es + push bx + mov ah,get_DTA + call int_21 + mov word ptr incoming_DTA+0,bx ; save callers DTA + mov word ptr incoming_DTA+2,es + pop bx + pop es + push ds + push dx + mov ah,set_DTA + lea dx,exec_DTA ; set for fake exec search + push cs + pop ds + call int_21 + pop dx + pop ds + mov ah,handle_fnd1 ; precess search by finds + mov expected_error,handle_no_more_files + +not_exec1: + + push es ; save append's ES + push bx ; save append's BX + mov es,incoming_ES ; must restore ES before doing the call ; fix for P37, GGA 9/10/87 + mov bx,incoming_BX ; must resatore user's ES:BX + + call int_21 ; try the open + + pop bx ; restore append's BX + pop es ; restore append's es + pushf ; save flags + cmp incoming_AX,exec_proc*256+0 ; exec pgm call + jne not_exec2 + push ds + push dx + push ax + mov ah,set_DTA + mov dx,word ptr incoming_DTA+0 ; restore callers DTA + mov ds,word ptr incoming_DTA+2 + call int_21 + pop ax + pop dx + pop ds +not_exec2: + popff + pushf + jnc found_it_remote ; all done + + cmp crit_err_flag,0 ; process critical errors + jne check_crit_err + + cmp ax,handle_path_not_found ; normal errors + je should_we_look_more + + cmp ax,expected_error ; was the error we found file not found? + je should_we_look_more ; yes, look some more + jmp no_more_to_try2 ; no, any other error, we pack it in + +should_we_look_more: + mov si,app_dirs_ptr ; yes, see if we should look more + cmp si,null ; should we try again? + je no_more_to_tryx + jmp try_another2 ; yes +no_more_to_tryx: + jmp no_more_to_try2 + +check_crit_err: + mov ext_err_flag,1 ; we need to set extended error info + mov ax,expected_error ; make ax look like we got file not found + mov ax_after_21,ax ; save it away so we can restore it below + popff ; get clags from stack + stc ; set the carry flag + pushf ; put 'em back + + jmp no_more_to_try2 + +found_it_remote: ; come here only if the file was found in + ; an appended directory + mov ax_after_21,ax ; save AX + + +; ;AN002; +; Find out if this process has the true_name flag set in thier PSP. ;AN002; +; At this point, DS:DX points to the true name of the found file ;AN002; +; ;AN002; + ;AN002; + push ax ; save some regs ;AN002; + save_regs + ;AN002; + mov ah,get_PSP ; function code for get PSP operation ;AN002; + call int_21 ; get the PSP, segment returned in BX ;AN002; + mov es,bx ; need to use it as a segment ;AN002; + mov di,PDB_Append ; get pointer to APPEND flag in PDB ;AN002; + ;AN002; + mov ax,es:[di] ; get APPEND flag into AX ;AN002; + test ax,true_name_flag ; is true name flag armed? ;AN002; + jz no_true_name ; no, don't copy true name ;AN002; + ;AN002; + sub ax,true_name_flag ; clear true name flag ;AN002; + mov es:[di],ax ; save it in PSP ;AN002; + ;AN002; + mov di,word ptr handle_ptr+0 ; get user's buffer pointer ES:DI ;AN002; + mov es,word ptr handle_ptr+2 ;AN002; + +; find out if this is a handle find or an open or an exec + + cmp incoming_AX,exec_proc*256+0 ; exec? + je no_true_name ; yes, do nothing with true name + ;AN002; + cmp incoming_AX,handle_fnd1*256+0 ; handle find? + jne not_hf ; no, go do the easy stuff + ;AN002; +; function we are doing is a handle find, must get part of true_name +; string from append path, part from DTA. Messy! + + lea si,try_dir ; buffer that has last APPEND path tried + + mov cx,true_name_count ; get number of chars in true_name dir ;AN002; + +copy_true_name_loop2: + mov ah,ds:[si] ; get byte of append dir path ;AN002; + mov es:[di],ah ; copy it to user's buffer ;AN002; + inc si ; in this loop, the null is not copied ;AN002; + inc di ;AN002; + loop copy_true_name_loop2 ;AN002; + +; put in the "\" + + mov ah,"\" ; get a \ + mov es:[di],ah ; copy it + inc di ; increment pointer + +; we have copied the first part of the string, now get the real filename +; from the DTA + + push es + push bx + + mov ah,get_DTA + call int_21 + push es + pop ds + mov si,bx + + pop bx + pop es + +copy_true_name_loop3: + mov ah,ds:[si+30] ; get byte of actual filename ;AN002; + mov es:[di],ah ; copy it to user's buffer ;AN002; + cmp ah,null ; is it a null? ;AN002; + je true_name_copied ; yes, all done ;AN002; + inc si ; in this loop the null is copied ;AN002; + inc di ;AN002; + jmp copy_true_name_loop3 ;AN002; + +not_hf: + mov si,dx ; make DS:SI point to true name + +copy_true_name_loop: ;AN002; + mov ah,ds:[si] ; get byte of true name ;AN002; + mov es:[di],ah ; copy it to user's buffer ;AN002; + cmp ah,null ; is it a null? ;AN002; + je true_name_copied ; yes, all done ;AN002; + inc si ;AN002; + inc di ;AN002; + jmp copy_true_name_loop ;AN002; + ;AN002; +true_name_copied: ;AN002; + ;AN002; +no_true_name: ;AN002; + restore_regs ; restore some regs ;AN002; + pop ax + ;AN002; + ;AN002; +no_more_to_try2: + + call ctrl_break_restore ; restore normal control break address + call crit_err_restore ; restore normal critical error address + +; find out if there is a need to set the extended error code + + cmp ext_err_flag,0 ; do we need to set the extended error code? + je no_ext_err2 ; no, finish up + lea dx,ext_err_dpl + call set_ext_err_code ; yes, go set the ext error info + +; reset flags, and pack it in + +no_ext_err2: + popff + restore_regs ; restore registers + pushf ; put the real flags on the stack + + jmp reset_stack ; fix stack, ret to caller + +page +;------------------------------------------------------------------- +; +; support routines for drive and path mode checking +; +; +;------------------------------------------------------------------- + + +check_for_drive: ; input: ES:SI -> original string + ; output: AX = 0 no drive present + ; output: AX = -1 drive present + + xor ax,ax ; assume no drive letter present + + cmp es: byte ptr [si+1],':' ; is the second char a ":"? + jne exit_check_for_drive ; no, skip setting the flag + + mov ax,-1 ; yes, set the flag + +exit_check_for_drive: + + ret + +;------------------------------------------------------------------- + +check_for_path: ; input: ES:SI -> original string + ; output: AX = 0 no path present + ; output: AX = -1 path present + + push si ; save pointer + + xor ax,ax ; assume no path present + + +; walk the string and look for "/", or "\". Any of these mean that a +; path is present + +walk_handle_string: + + push ax ;AN006; + mov al,es: byte ptr [si] ; is this a dbcs char? ;AN006; + call Chk_DBCS ;AN006; + pop ax ;AN006; + ;AN006; + jnc no_dbcs1 ; no, keep looking ;AN006; + + add si,2 ; yes, skip it and the next char ;AN006; + jmp walk_handle_string ; the next char could be a "\", but ;AN006; + ; would not mean a path was found ;AN006; + ;AN006; +no_dbcs1: ;AN006; + cmp es: byte ptr [si],"\" ; is the char a "\"? + je found_path ; yes, set flag and return + cmp es: byte ptr [si],"/" ; is the char a "/"? + je found_path ; yes, set flag and return + cmp es: byte ptr [si],0 ; is the char a null + je exit_check_for_path ; yes, got to the end of the + ; handle string + + inc si ; point to next char + jmp walk_handle_string ; and look again + +found_path: + mov ax,-1 ; yes, set the flag + +exit_check_for_path: + pop si ; restore si + ret + +page +;----------------------------------------------------------------------------- +; Entry point for interrupt 2f handler +;----------------------------------------------------------------------------- + +intfcn_hook: + cmp ah,append_2f ; is this function call for append? +;;;;;; je do_appends ; @@12 + jne ih_10 ; @@12 + jmp do_appends ; @@12 +ih_10: ; @@12 + cmp ah,applic_2f ; is this function call for applications + je do_applic + jmp pass_it_on + +do_applic: + cmp dx,-1 ; not COMMAND call + jump NE,pass_it_on + cmp al,0 ; match name request + jne ck01 + + mov cmd_buf,bx ; save CMDBUF offset + call check_cmd_name + jne no_internal1 + mov al,append_inst ; inidicate I want this command +no_internal1: + iret + +ck01: + cmp al,1 ; match name request + jne ck02 + +; save pointer to parser + + mov word ptr pars_off+0,di ; ES:DI points to COMMAND.COM's parser + mov word ptr pars_off+2,es ; save it for later + + mov cmd_env,bx ; save env pointer address + call check_cmd_name + jne no_internal2 + call COMMAND_begin ; process internal command +no_internal2: + iret + +ck02: +; cmp al,2 ; set COMMAND active ; @@13; @@09 +; jne ck03 ; @@13; @@09 +; mov cmd_active,1 ; @@13; @@09 +; iret ; @@13; @@09 +ck03: ; @@13; @@09 +; cmp al,3 ; set COMMAND in active ; @@13; @@09 +; jne ck04 ; @@13; @@09 +; mov cmd_active,0 ; @@13; @@09 +; iret ; @@13; @@09 +ck04: ; @@13; @@09 + jmp pass_it_on + +;******************************************************************************* +; The following old code is commented out. @@12 +;******************************************************************************* +;check_cmd_name: ; see if internal APPEND +; push es +; push cs +; pop es +; push di +; push cx +; push si +; cmp ds:byte ptr[si],6 ; length must match +; jne skip_comp +; comp append_id,6,[si+1] ; see if APPEND is command +;skip_comp: +; pop si +; pop cx +; pop di +; pop es +; ret +;********************************************************************* +check_cmd_name: ; See if APPEND @@12 + push ax ; @@12 + push si ; @@12 + push cx ; @@12 + push di ; @@12 + push es ; @@12 + mov si,cmd_buf ; DS:SI -> cmd buf ended with cr @@12 + add si,2 ; 1st 2 bytes garbage @@12 + ; @@12 +ccn_skip_leading: ; @@12 + lodsb ; skip leading stuff @@12 + + call Chk_DBCS ; find out if this is DBCS ;AN006; + jnc no_dbcs2 ; no, keep looking ;AN006; + lodsb ; yes, skip it and the next byte ;AN006; + jmp ccn_skip_leading ; the second byte will be skipper when ;AN006; + ; we go back through ;AN006; + +no_dbcs2: ;AN006; + cmp al," " ; blank @@12 + je ccn_skip_leading ; @@12 + cmp al,tab_char ; tab @@12 + je ccn_skip_leading ; @@12 + cmp al,"," ; comma @@12 + je ccn_skip_leading ; @@12 + cmp al,"=" ; equal @@12 + je ccn_skip_leading ; @@12 + cmp al,";" ; semi-colon @@12 + je ccn_skip_leading ; @@12 + cmp al,"\" ; back slash @@12 + je ccn_skip_leading ; @@12 + cmp al,cr ; bad ret for early terminate @@12 + jne ccn_02 ; @@12 + cmp al,0 ; reset z for no match @@12 + jmp ccn_ret ; @@12 +ccn_02: ; @@12 + mov di,si ; di -> beginning of possible @@12 + dec di ; "APPEND " string @@12 + lodsb ; @@12 + cmp al,":" ; @@12 + jne ccn_cont ; @@12 + mov di,si ; @@12 + lodsb ; @@12 +ccn_cont: ; @@12 + call Chk_DBCS ;AN006; + jnc no_dbcs3 ; no, carry on ;AN006; + add si,2 ; yes, skip it and the next byte ;AN006; + jmp ccn_20 ;AN006; + ;AN006; +no_dbcs3: ;AN006; + cmp al,"\" ; move di up upon "\" @@12 + jne ccn_20 ; @@12 + mov di,si ; @@12 +ccn_10: ; @@12 + lodsb ; @@12 + jmp ccn_cont ; @@12 +ccn_20: ; @@12 + cmp al," " ; look for separator @@12 + je ccn_30 ; if found, then have command @@12 + cmp al,"=" ; @@12 + je ccn_30 ; @@12 + cmp al,cr ; @@12 + je ccn_30 ; @@12 + cmp al,tab_char ; @@12 + je ccn_30 ; @@12 + cmp al,"," ; @@12 + je ccn_30 ; @@12 + cmp al,";" ; @@12 + jne ccn_10 ; @@12 + +ccn_30: ; @@12 + sub si,di ; @@12 + cmp si,7 ; @@12 + jne ccn_ret ; no match @@12 + ; @@12 + mov si,di ; @@12 + chkchar "A" ; look for "APPEND" string @@12 + chkchar "P" ; @@12 + chkchar "P" ; @@12 + chkchar "E" ; @@12 + chkchar "N" ; @@12 + chkchar "D" ; @@12 + ; exit with z set for match @@12 +ccn_ret: ; @@12 + pop es ; @@12 + pop di ; @@12 + pop cx ; @@12 + pop si ; @@12 + pop ax ; @@12 + ret ; @@12 + +page +;------------------------------------------------------------------- ;AN000; +; ;AN000; +; do_appends ;AN000; +; ;AN000; +; This is the INT 2F handler for the APPEND ;AN000; +; subfunction ;AN000; +; ;AN000; +; New functions added for 3.30: ;AN000; +; ;AN000; +; ;AN000; +; ;AN000; +; Get /X status ;AN000; +; ;AN000; +; Input: AX = B706 ;AN000; +; ;AN000; +; Output: BX = 0000 /X not active ;AN000; +; = 0001 /X active ;AN000; +; ;AN000; +; ;AN000; +; ;AN000; +; Set /X status ;AN000; +; ;AN000; +; Input: AX = B707 ;AN000; +; ;AN000; +; BX = 0000 turn /X off ;AN000; +; BX = 0001 turn /X on (active) ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; +; +do_appends: + cmp al,are_you_there ; is the function request for presence? + jne ck1 + + mov al,-1 ; set flag to indicate we are here + iret ; return to user + +ck1: + cmp al,dir_ptr ; is the function request for pointer? + jne ck2 + + les di,dword ptr dirlst_offset ; return dirlist pointer to caller + iret + +ck2: + cmp al,get_app_version ; is the function request for version? + jne ck3 ; no, check for next function + + mov ax,-1 ; yes, set NOT NETWORK version + iret + +ck3: + cmp al,tv_vector ; is the function request for TV vector? + jne ck4 ; no, check for old dir ptr + + mov tv_vec_seg,es ; yes, save the TV vector + mov tv_vec_off,di + + push cs ; set ES:DI to tv ent pnt + pop es ; + lea di,tv_entry + + xor byte ptr tv_flag,TV_TRUE ; set flag ;AN000; + iret + +ck4: ; + cmp al,old_dir_ptr ; is it the old dir ptr + jne ck5 ; no, pass it on + + push ds + push cs + pop ds + + call sysloadmsg ;AN000; + ;AN000; + mov ax,1 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + + pop ds + mov al,1 + call terminate ; exit to DOS ; @@05 + +ck5: ; + cmp al,DOS_version ; is it the new version check + jne ck6 ; no, pass it on + + mov ax,mode_flags ; set mode bits + xor bx,bx ; destroy registers + xor cx,cx + mov dl,byte ptr version_loc ; major version num + mov dh,byte ptr version_loc+1 ; minor version num + iret + +ck6: ;AN000; + cmp al,get_state ; is it get state call? ;AN001; + jne ck7 ; no, look some more ;AN000; + ;AN000; + mov bx,mode_flags ; get mode bits ;AN000; + iret ; return to user ;AN000; + ;AN000; +ck7: ;AN000; + cmp al,set_state ; is it set state call? ;AN001; + jne ck8 ; no, look some more ;AN000; + ;AN000; + mov mode_flags,bx ; save the new state ;AN001; + iret ;AN000; + ;AN000; +ck8: ;AN000; + + cmp al,true_name ; is it the set true name function? ;AN002; + jne ck9 ; no, look some more ;AN002; + ;AN002; + push ax ; save some regs ;AN002; + push bx ;AN002; + push es ;AN002; + push di ;AN002; + ;AN002; + ;AN002; +; get the PSP and then get the APPEND flags byte + + mov ah,get_PSP ; function code to get PSP address ;AN002; + call int_21 ; get the PSP address ;AN002; + mov es,bx ; need to use it as a segment ;AN002; + mov di,PDB_Append ; get pointer to APPEND flag in PDB ;AN002; + ;AN002; +; is the flag already set? + + mov ax,es:[di] ; get APPEND flag into AX ;AN002; + test ax,true_name_flag ; is it set? ;AN002; + jnz no_set_true_name ; yes, do nothing ;AN002; + ;AN002; +; set the true_name flag + +set_true_name: ;AN002; + add ax,true_name_flag ; set true name flag ;AN002; + mov es:[di],ax ; save in PSP ;AN002; + ;AN002; +no_set_true_name: + pop di ; restore some regs ;AN002; + pop es ;AN002; + pop bx ;AN002; + pop ax ;AN002; + ;AN002; + iret ; return ;AN002; + ;AN002; +ck9: ;AN002; + +;------------------------------------------------------------------- +; fill in additional 2F functions here +;------------------------------------------------------------------- + +pass_it_on: ; the function call (ah) was not for append + jmp dword ptr intfcn_Offset ; jump to old INT 2f + +page +;----------------------------------------------------------------------------- +; Entry point for interrupt 24 handler +;----------------------------------------------------------------------------- + +crit_err_handler: + + mov crit_err_flag,0ffh ; set critical error flag + mov al,3 ; fail int 21h + iret + +page +;----------------------------------------------------------------------------- +; miscellaneous routines +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; tv_barrier +;----------------------------------------------------------------------------- + +tv_barrier: + + cmp tv_flag,TV_TRUE ; in Topview ;AN000; + jne no_barrier + + push ax + mov ax,2002h ; wait on DOS barrier + int 2Ah + pop ax +no_barrier: + ret + +;----------------------------- +; check_config - this routine is called by both the FCB and handle open +; code. I checks the net_config flag to see if it is zero, if so it +; does an installation check. If it is non-zero, nothing is done. + +check_config: + + push ax ; save a few registers + push bx + +; examine the config flag to see if we already know what config we have + + cmp net_config,0 + jne do_not_look ; we know config already + +; the flag word has not been set before, go find out what config we have + + mov ax,0b800h ; installation code function code + int 2fh ; do the installation check + + mov net_config,bx ; save flag word for later + +do_not_look: + pop bx ;restore regs and leave + pop ax + ret + +;*( Chk_DBCS ) ************************************************************* +;* * +;* Function: Check if a specified byte is in ranges of the DBCS lead bytes* +;* Attention: If your code is resident, comment out the lines marked * +;* ;** . * +;* * +;* Input: * +;* AL = Code to be examined * +;* * +;* * +;* Output: * +;* If CF is on then a lead byte of DBCS * +;* * +;* Register: * +;* FL is used for the output, others are unchanged. * +;* * +;*************************************************************************** +Chk_DBCS PROC + PUSH DS + PUSH SI +; CMP CS:DBCSEV_SEG,0 ; ALREADY SET ? ;** +; JNE DBCS00 ;** + MOV SI,OFFSET EVEV ; SET DEFAULT OFFSET ;** + PUSH CS ;** + POP DS ; SET DEFAULT SEGMENT ;** + PUSH AX + MOV AX,6300H ; GET DBCS EV CALL + INT 21H + MOV CS:DBCSEV_OFF,SI ;** + MOV CS:DBCSEV_SEG,DS ;** + POP AX +DBCS00: + MOV SI,CS:DBCSEV_OFF ;** + MOV DS,CS:DBCSEV_SEG ;** +DBCS_LOOP: + CMP WORD PTR [SI],0 + JE NON_DBCS + CMP AL,[SI] + JB DBCS01 + CMP AL,[SI+1] + JA DBCS01 + STC + JMP DBCS_EXIT +DBCS01: + ADD SI,2 + JMP DBCS_LOOP +NON_DBCS: + CLC +DBCS_EXIT: + POP SI + POP DS + RET +Chk_DBCS ENDP + + +;----------------------------- +; append_fname - glues the fname onto the end of the dir to try + +append_fname: + push es + push ds + pop es + lea di,try_dir ; destination, sort of (dir name) + lea si,fname ; source (filename) + +; find the end of the dir name + + mov dbcs_fb,-1 ; set flag for no dbcs first byte chars ;AN006; + +walk_dir_name: + mov al,byte ptr [di] ; get a char from dir name + cmp al,null ; are we at the end? + je end_of_dir ; yes, add on the fname + + call Chk_DBCS ; char is in al ;AN006; + jnc no_dbcs4 ; no, keep looking ;AN006; + mov dbcs_fb,di ; save offset ;AN006; + inc di ; skip second byte + +no_dbcs4: + inc di ; no, keep stepping + jmp walk_dir_name + +; now it is time to append the filename + +end_of_dir: + mov al,byte ptr [di-1] ; get last char of dir name + cmp al,"\" ; is it a dir seperator? + jne check_next_dir_sep ; no, check the next dir sep char ;AN006; + ;AN006; + sub di,2 ; yes, must find out if real dir sep ;AN006; + ; or DBCS second byte ;AN006; + cmp dbcs_fb,di ; is the char before our dir sep a DBCS ;AN006; + ; first byte? ;AN006; + jne no_dbcs4a ; no, must check for the next dir sep ;AN006; + ; yes, this means we must put in a dir sep ;AN006; + add di,2 ; restore di ;AN006; + jmp put_in_dir_sep ; put int the dir sep char ;AN006; + ;AN006; +no_dbcs4a: ;AN006; + add di,1 ; restore di, then check next dir sep ;AN006; + +check_next_dir_sep: + cmp al,"/" ; is it the other dir seperator? + je add_fname ; yes, no need to add one +put_in_dir_sep: ;AN006; + mov al,"\" ; get dir seperator + stosb ; add to end of dir + +add_fname: + lodsb ; get a char from fname + stosb ; copy the char + cmp al,null ; are we at the and of the filename? + je eo_name ; yes, all done! + jmp add_fname + + + + + + + +eo_name: + pop es + ret + + +;----------------------------- +; get_fname strips out the 8.3 filename from the original ASCIIZ string +; +; INPUT: ES:SI points to original string +; DS:DI points to area for filename + +get_fname: + + mov bx,si ; save the pointer + mov dbcs_fb,-1 ; set the dbcs flag off ;AN006; + +gfn1: + mov ah,ES:byte ptr [si] ; get a char from the source + cmp ah,null ; is it a null? + je got_the_end ; yes, we found the end + + call chk_dbcs ; is this char a DBCS first byte? ;AN006; + jnc no_dbcs5 ; no, carry on + mov dbcs_fb,si ; yes, save pointer + inc si ; skip second byte + +no_dbcs5: + inc si ; no, point to next char + jmp gfn1 ; loop till end found + +got_the_end: + mov ah,ES:byte ptr [si] ; get a char + cmp ah,"/" ; did we find a / + je went_too_far ; yes, we found the start + cmp ah,"\" ; did we find a \ + je found_bslash ; yes, we found the start ;AN006; + cmp ah,":" ; did we find a : + je went_too_far ; yes, we found the start + cmp si,bx ; are we back to the original start? + je got_the_beg ; yes, we found the start of the fname + dec si ; step back a char, then look some more + jmp got_the_end + +found_bslash: ; found a backslash, must figure out if ;AN006; + ; is second byte of DBCS ;AN006; + dec si ; point to next char ;AN006; + cmp si,dbcs_fb ; do they match? + jne no_dbcs5a ; no, fix up si and carry on ;AN006; + dec si ; skip dbcs byte and loop some more ;AN006; + jmp got_the_end ;AN006; + +no_dbcs5a: ;AN006; + inc si ; went too far by one extra ;AN006; + ;AN006; +went_too_far: + inc si ; went one char too far back + +; ES:SI now points to the beginning of the filename + +got_the_beg: + mov ah,ES:byte ptr [si] ; get a char from the source + mov byte ptr [di],ah ; copy to dest + cmp ah,null ; did we just copy the end? + je done_with_fname ; yes, all done + inc si ; no, get the next char + inc di + cmp di,offset app_dirs_ptr ; make sure we dont try to copy past the + je done_with_fname ; area + jmp got_the_beg + +done_with_fname: + ret + +;----------------------------- +; this code executed to return to caller after APPEND's stack has been +; initialized + +reset_stack: + +; reset the stack ;AN002; + + popff ; restore flags from real open + mov ss,Stack_Segment ; Get original stack segment + mov sp,Stack_Offset ; Get original stack pointer + pushf ; put the flags on the old stack + + +;----------------------------- +; before jumping to this routine, SS:SP must point to the caller's stack, +; and the flags from the real INT 21 operation must have been pushed + +set_return_flags: + +; must be sure to clear the true_name flag before leaving ;AN002; + ;AN002; + push ax ; save some regs ;AN002; + push bx ;AN002; + push es ;AN002; + push di ;AN002; + ;AN002; + mov ah,get_PSP ; function code for get PSP operation ;AN002; + call int_21 ; get the PSP, segment returned in BX ;AN002; + mov es,bx ; need to use it as a segment ;AN002; + mov di,PDB_Append ; get pointer to APPEND flag in PDB ;AN002; + ;AN002; + mov ax,es:[di] ; get APPEND flag into AX ;AN002; + test ax,true_name_flag ; is true name flag armed? ;AN002; + jz reset_stack2 ; no, don't copy true name ;AN002; + ;AN002; + sub ax,true_name_flag ; clear true name flag ;AN002; + mov es:[di],ax ; save it in PSP ;AN002; + ;AN002; + ;AN002; +reset_stack2: ;AN002; + ;AN002; + pop di ; restore ;AN002; + pop es ;AN002; + pop bx ;AN002; + pop ax ;AN002; + ;AN002; + cmp tv_flag,TV_TRUE ;AN000; + jne tv_flag_not_set + + mov ax,2003h ; clear open barrier + int 2Ah + + +; pop down to the old flags on the user's stack + +tv_flag_not_set: + + cmp incoming_AX,exec_proc*256+0 ; need to do exec + jne not_exec3 + popff ; discard bad flags + mov ax,incoming_AX ; set exec parms + + push ds ; save DS, this must be done ;an005; + ; to pervent DS from being trashed on return to caller ;an005; + + push cs + pop ds + lea dx,try_dir + mov bx,incoming_BX + mov es,incoming_ES + call int_21 ; issue the exec + + pop ds ; restore DS ; an005; + + pushf + +not_exec3: + popff ; get flags from real int 21 (old stack) + pop temp_IP_save ; save IP, CS + pop temp_CS_save + lahf ; save flags in AH + popff ; pop old flags off stack + sahf ; replace old with new + +; push the new flags onto the stack, then fix CS and IP on stack + + pushf ; push new flags onto stack + push temp_CS_save ; restore IP, CS + push temp_IP_save + mov ax,AX_after_21 ; Set AX as it was after open + + call crit_sect_reset ; clear the critical section flag + iret ; return to the calling routine + + +;----------------------------- +; This routine is used to extract an appended dir from the dir list +; On entry, DS:DI points to an area for the appended dir +; and ES:SI points to the source string + +get_app_dir: + + xor cx,cx ; keep a count of chars in cx ;AN003; +copy_dir: + mov ah,es:byte ptr [si] ; get the char, and copy it into dest + cmp ah,null ; find a null? + je no_more_dirs ; yes, inform caller that this is the last one + + cmp ah,";" ; check to see if we are at the end of a dir + je update_pointer ; yes, + + mov byte ptr [di],ah ; if not null or semi-colon, then copy it + inc si ; increment both pointers + inc di + inc cx ; count of chars ;AN003; + jmp copy_dir ; do it some more + +update_pointer: + inc si ; point to next char + mov ah,es:byte ptr [si] ; get char ; @@16 + cmp ah,null ; did we reach the end of the dir list? + je no_more_dirs ; + + cmp ah,";" ; is is a semi-colon + je update_pointer + jmp all_done + + +no_more_dirs: + xor si,si ; set end search flag + +all_done: + mov byte ptr [di],null ; null terminate destination + ret ; return to caller + +;----------------------------- +; set ctrl-break check off +; first, save the old state so we can restore it later, +; then turn ctrl-break checking off + +ctrl_break_set: + + mov ah,ctrl_break ; function code for ctrl-break check + xor al,al ; 0 = get current state + call int_21 ; call DOS INT 21 handler + + mov ctrl_break_state,dl ; save the old ctrl-break state + + mov ah,ctrl_break ; function code for ctrl-break check + mov al,01 ; set current state + xor dl,dl ; 0 = off + call int_21 ; call DOS INT 21 handler + ret + + +;----------------------------- +; restore ctrl-break checking flag to the way it was +ctrl_break_restore: + mov ah,ctrl_break ; function code for ctrl-break check + mov al,01 ; set current state + mov dl,ctrl_break_state ; get the way is was before we messed with it + call int_21 ; call DOS INT 21 handler + ret + +;----------------------------- +; restore ctrl-break checking flag to the way it was +ctrl_break_rest: + mov ah,ctrl_break ; function code for ctrl-break check + mov al,01 ; set current state + mov dl,ctrl_break_state ; get the way is was before we messed with it + call int_21 + ret + +;----------------------------- +; +crit_err_set: + mov crit_err_flag,0 ; clear the critical error flag + + mov ax,get_crit_err ; Get INT 24h vector + call int_21 ; call DOS INT 21 handler + + mov crit_vector_offset,bx ; Save it + mov ax,es ; es hase segment for resident code + mov crit_vector_segment,ax + + lea dx,crit_err_handler ; DS:DX = New INT 21h vector + mov ax,set_crit_err ; function code for setting critical error vector + call int_21 ; call DOS INT 21 handler + ret ; go back to the caller + + +;----------------------------- +; +crit_err_restore: + push ds ; save ds for this function + mov ax,set_crit_err ; function code for setting critical error vector + mov dx,crit_vector_offset ; get old int 24 offset + mov ds,crit_vector_segment ; get old int 24 segment + call int_21 ; call INT 21 + pop ds + ret + +;----------------------------- +; crit_sect_set - issues an enque request to the server to protect +; against reentry. This request is issued only if the network is started, +; and then, only for RCV, MSG, and SRV configurations +crit_sect_set: + push ax + push bx + push di + push es + + mov ax,net_config ; check the server config flag + cmp ax,0 ; is it zero? + je dont_set_crit_sect ; yes, skip it + + cmp ax,redir_flag ; is it a redir? + je dont_set_crit_sect ; yes, skip it + ; otherwise, issue the request + +; the config flag was not zero or redir, so set crit section + + mov ah,NETSYSUTIL + mov al,NETENQ + mov bx,TCBR_APPEND + int 2Ah + +dont_set_crit_sect: ; because of the config we don't want + pop es ; to set critical section + pop di + pop bx + pop ax + ret + +;----------------------------- +; +crit_sect_reset: + push ax + push bx + + mov ax,net_config ; check the server config flag + cmp ax,0 ; is it zero? + je not_set ; yes, skip it + + cmp ax,redir_flag ; is it a redir? + je not_set ; yes, skip it + + mov ah,NETSYSUTIL ; turn critical section off + mov al,NETDEQ + mov bx,TCBR_APPEND + int 2Ah + +not_set: + pop bx + pop ax + ret + + +;----------------------------- +; save_first_ext_err - this routine is used to save the extended +; error info after the first FCB open. +save_first_ext_err: + + push ax + + mov ax,ext_err_dpl.DPL_AX ; copy all registers + mov save_ext_err.DPL_AX,ax + mov ax,ext_err_dpl.DPL_BX + mov save_ext_err.DPL_BX,ax + mov ax,ext_err_dpl.DPL_CX + mov save_ext_err.DPL_CX,ax + mov ax,ext_err_dpl.DPL_DX + mov save_ext_err.DPL_DX,ax + mov ax,ext_err_dpl.DPL_SI + mov save_ext_err.DPL_SI,ax + mov ax,ext_err_dpl.DPL_DI + mov save_ext_err.DPL_DI,ax + mov ax,ext_err_dpl.DPL_DS + mov save_ext_err.DPL_DS,ax + mov ax,ext_err_dpl.DPL_ES + mov save_ext_err.DPL_ES,ax + + pop ax + ret + +;----------------------------- +; get_ext_err_code - this routine is used to get the extended error +; info for the error that cause append to start its search + +get_ext_err_code: + push ax ; save register that are changed by this + push bx ; DOS function + push cx + push di + push si + push es + push ds + +; get the extended error information + + mov ah,59h ; function code for get extended error + xor bx,bx ; version number + call int_21 ; get the extended error + +; save it away in a DPL for set_ext_error_code +; all fields in the DPL will be filled in except the last three, +; which will be left at zero + + mov ext_err_dpl.DPL_AX,ax + mov ext_err_dpl.DPL_BX,bx + mov ext_err_dpl.DPL_CX,cx + mov ext_err_dpl.DPL_DX,dx + mov ext_err_dpl.DPL_SI,si + mov ext_err_dpl.DPL_DI,di + mov ext_err_dpl.DPL_DS,ds + mov ext_err_dpl.DPL_ES,es + + +; restore regs and return + + pop ds + pop es ; restore registers + pop si + pop di + pop cx + pop bx + pop ax + ret + +;----------------------------- +; set_ext_err_code - this routine is used to get the extended error +; info for the error that cause append to start its search +; CS:DX points to return list +set_ext_err_code: + push ax ; save register that are changed by this + push ds ; DOS function + +; get the extended error information + + mov ah,DOSSERVER ; function code for DOSSERVER call + mov al,DOSSETERROR ; sub-function code for set extended error + push cs + pop ds + call int_21 ; set the extended error + +; restore regs and return + + pop ds ; restore registers + pop ax + ret +page +;----------------------------- +; This routine is used to initiate DOS calls from within the APPEND interrupt +; handlers. An INT instruction can not be used because it would cause APPEND +; to be re-entered. +; +; SS, SP saved incase call is EXEC which blows them away +int_21: ; + cmp tv_flag,TV_TRUE ; see if being re-entered ;AN000; + jne use_old_vec ; yes, pass through to DOS + + pushf ; to comp for iret pops + call dword ptr tv_vec_off ; Call INT 21h + ret ; + +use_old_vec: + cmp vector_segment,0 ; not installed yet + je use_int + + pushf ; to comp for iret pops + call dword ptr vector_offset ; Call INT 21h + ret ; + +use_int: + int DOS_function + ret +page +;----------------------------- +; This routine is used to locate the current APPEND path string +; result to ES:DI + +address_path: +address_status: ; @@13 + test mode_flags,E_mode + jnz get_env_mode + +address_pathx: + mov ax,append_2f*256+dir_ptr ; get from buffer + int int_function + clc + ret + +get_env_mode: ; get from environment +; cmp cmd_active,0 ; different logic ; @@13; @@09 +; jne use_cmd_env ; if in COMMAND ; @@13; @@09 + push bx + mov ah,get_PSP + call int_21 ; get the PSP + mov es,bx + mov bx,002ch ; address environment + mov ax,es:word ptr[bx] + mov es,ax + pop bx + cmp ax,0 ; PSP pointer is set + je address_pathx ; @@13 +use_cmd_env: ; @@13 +; cmp cmd_env,0 ; have not set my pointer yet +; je address_pathx ; @@13 +; mov es,cmd_env ; @@13 +env_mode1: + mov di,0 ; start at start + cmp es:byte ptr[di],0 ; no environment + je no_appendeq +find_append: + cmp es:word ptr[di],0 ; at environment end + je no_appendeq + push di + push si + push cx + push ds + push cs + pop ds + comp ,6+1,append_id ; string = "APPEND=" + pop ds + pop cx + pop si + pop di + je at_appendeq + inc di + jmp find_append +at_appendeq: ; must insure this is @@17 + cmp di,0 ; genuine "APPEND=" string @@17 + je at_appendeq_genuine ; if start of environ ok @@17 + dec di ; else check that 0 @@17 + cmp es:byte ptr[di],0 ; precedes string @@17 + je at_appendeq_10 ; jmp if ok @@17 + add di,8 ; else cont.search after @@17 + jmp find_append ; "=" @@17 +at_appendeq_10: ; @@17 + inc di ; @@17 +at_appendeq_genuine: ; @@17 + add di,6+1 ; skip APPEND= + cmp es:byte ptr[di],0 ; null value + je no_appendeq ; treat as not found + cmp es:byte ptr[di]," " + je no_appendeq + cmp es:byte ptr[di],";" + je no_appendeq + clc ; set ok + ret + +no_appendeq: ; not found, use default + lea di,semicolon ; null list + push cs + pop es + stc ; set error + ret + +;----------------------------- ; @@03 +; This routine is used to locate the current APPEND path string ; @@03 +; result to ES:DI. Used by APPEND status. ; @@03 + +;address_status: ; @@13; @@03 +; test mode_flags,E_mode ; @@13; @@03 +; jump Z,address_pathx ; @@13; @@03 +; jmp use_cmd_env ; @@13; @@03 + +cap_dl: ; convert dl to uppercase + cmp dl,"a" ; find out if we have a lower case; @@14 + jb cap_dlx ; char ; @@14 + cmp dl,"z" ; @@14 + ja cap_dlx ; @@14 + sub dl,"a"-"A" ; convert char to upper case ; @@14 +cap_dlx: + ret + +; end_address: ; this is the end of the TSR stuff ;AN002; + +page +;----------------------------------------------------------------------------- +; Main routine. Used to determine if APPEND has been loaded +; before. If not, load resident portion of APPEND. Then handle setting +; or displaying appended directory list. +;----------------------------------------------------------------------------- + +main_begin: ; DOS entry point + + mov ax,seg mystack ; set up stack + mov ss,ax + lea sp,mystack + + cld + + mov res_append,0 ; set external copy ; @@05 + + push cs ; make DS point to CS + pop ds + + push cs ; make ES point to CS + pop es + + +; find out if append has been loaded ; @@04 + ; @@04 + mov ah,append_2f ; int 2f function code for append ; @@04 + mov al,are_you_there ; function code to ask if append ; @@04 + ; has been loaded ; @@04 + int int_function ; @@04 + ; @@04 + cmp al,append_inst ; is append there? ; @@04 + jne not_there_yet ; no ; @@04 + + mov dx,0 ; set for network version ; @@07 + mov ah,append_2f ; int 2F function code for append ; @@07 + mov al,DOS_version ; function code for get version ; @@07 + int int_function ; @@07 + cmp dx,word ptr version_loc ; does the version match? ; @@07 + jne bad_append_ver ; no, cough up an error messsage ; @@07 + + + call sysloadmsg ;AN000; + ;AN000; + mov ax,9 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; +; mov cx,len_second_APPEND_msg; length of string ;AN000; ; @@04 +; lea dx,second_APPEND_msg ; second load message ;AN000; ; @@04 +; call print_STDERR ; display error message ;AN000; ; @@04 +; lea dx,crlf ; carriage return, line feed ; @@04 +; mov cx,crlf_len ; length of string ; @@04 +; call print_STDERR ; @@04 + ; @@04 + mov al,0fch ; second load ; @@05 + call terminate ; exit to DOS ; @@05 + +bad_append_ver: ; append version mismatch ; @@07 + call sysloadmsg ;AN000; + ;AN000; + mov ax,1 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; +; mov cx,len_bad_append_msg ;AN000; ; @@07 +; lea dx,bad_append_msg ; bad app message ;AN000; ; @@07 +; call print_STDERR ;AN000; ; @@07 +; lea dx,crlf ; carriage return, line feed ; @@07 +; mov cx,crlf_len ; length of string ; @@07 +; call print_STDERR ; @@07 + mov ax,0feh ; bad APPEND version ; @@05 + call terminate ; exit to DOS ; @@05 + +not_there_yet: ; @@04 + + mov cs:initial_pass,-1 ; set a flag for initial pass ;AN007; + call do_command ; do actual APPEND + + mov bx,4 ; close all standard files +do_closes: + mov ah,3eh ; close file handle + call int_21 + dec bx + jns do_closes + + call set_vectors ; set append vectors on success ; @@05 + + call Release_Environment ; release the environmental vector space ;an007; dms; + + lea dx,end_address+15 ; normal end + mov cl,4 ; calc end address in paragraphs + shr dx,cl + mov ah,get_PSP ; calc space from PSP to my code ; @@02 + call int_21 ; @@02 + mov ax,cs ; @@02 + sub ax,bx ; @@02 + add dx,ax ; calc length to keep ; @@02 + mov al,0 ; exit with no error + mov ah,term_stay + call int_21 + +page + +COMMAND_begin: ; COMMAND entry point + save_regs + mov word ptr cmd_name@+0,si ; save internal command buffer @ + mov word ptr cmd_name@+2,ds + cld + + mov abort_sp,sp ; save sp for aborts ; @@05 + mov res_append,1 ; set resident copy ; @@05 + call do_command ; do actual APPEND +abort_exit: ; exit to abort append ; @@05 + mov sp,abort_sp ; @@05 + + push es + push di + les di,cmd_name@ + mov es:byte ptr[di],0 ; set no command now + pop di + pop es + + cmp ax,0 ; error + jne no_E_mode + test mode_flags,E_mode ; no /E processing + jz no_E_mode + + mov ax,append_2f*256+dir_ptr; int 2f function code for append + int int_function + push es + pop ds + mov si,di + +; mov ah,get_PSP ; set new command +; call int_21 + mov bx,ss + mov es,bx + mov bx,cmd_buf ; command line iput buffer + inc bx ; skip max length + mov es:byte ptr[bx],3+1+6+1 + mov di,bx ; address command line buffer + inc di ; skip current length + push ds + push si + push cs + pop ds + move ,3+1+6+1,setappend_name ; set in "SET APPEND=" + pop si + pop ds + cmp ds:byte ptr[si],";" ; null list is special case + jne copy_path + mov al," " + stosb + inc es:byte ptr[bx] + jmp short copy_path_done +copy_path: + lodsb + cmp al,0 + je copy_path_done + stosb + inc es:byte ptr[bx] + jmp copy_path +copy_path_done: + mov es:byte ptr[di],cr ; set end delimiter + + les di,cmd_name@ + mov al,3 ; SET length + stosb + push cs ; @@06 + pop ds ; @@06 + move ,8,set_name ; set up "SET" command + + mov ax,0 ; set to do SET +no_E_mode: + + restore_regs + ret + +page + +do_command: ; APPEND process + +; set ctrl-break check off +; first, save the old state so we can restore it later, +; then turn ctrl-break checking off + + mov ah,ctrl_break ; function code for ctrl-break check + xor al,al ; 0 = get current state + call int_21 + + mov ctrl_break_state,dl ; save the old ctrl-break state + + mov ah,ctrl_break ; function code for ctrl-break check + mov al,01 ; set current state + xor dl,dl ; 0 = off + call int_21 + +; find out if append has been loaded + + mov ah,append_2f ; int 2f function code for append + mov al,are_you_there ; function code to ask if append + ; has been loaded + int int_function + + cmp al,append_inst ; is append there? + jne not_already_there ; yes, don't try to put it + jmp already_there ; yes, don't try to put it + ; there again + +; get DOS version and decide if it is in the allowed range for +; APPEND + +not_already_there: + mov ah,get_version ; lets find out if we should do it + call int_21 ; try the open + cmp ax,expected_version ; compare with DOS version + jne bad_DOS + + jmp check_assign ; valid range + ; lets see if assign has been loaded + +; Break it to the user that he's trying to do an APPEND with +; the wrong DOS version + +bad_DOS: + cmp al,01 ; DOS 1x or below has no handle fcns ; fixed P134 9/10/87 - gga + ja use_STDERR +; lea dx,bad_DOS_msg ; bad DOS message ;AN000; +; mov ah,print_string ;AN000; +; call int_21 ;AN000; + call sysloadmsg ;AN000; + ;AN000; + mov ax,8 ; message number ;AN000; + mov bx,NO_HANDLE ; no handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + + + call ctrl_break_rest + int termpgm ; return to DOS ; @@05 + +use_STDERR: + ;AN000; + call sysloadmsg ;AN000; + ;AN000; + mov ax,8 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + +; mov cx,len_bad_DOS_msg ; length of string ;AN000; +; lea dx,bad_DOS_msg ; bad DOS message ;AN000; +; call print_STDERR ; display error message ;AN000; + + call ctrl_break_rest + mov al,0ffh ; bad DOS version ; @@05 + call terminate ; exit to DOS ; @@05 + +check_assign: + mov ax,0600h + int 2fh + or al,al + jnz assign_there + jmp check_TopView ; ASSIGN has not been loaded, ; @@01 + +; ASSIGN has been loaded before APPEND, bad news! + +assign_there: + call sysloadmsg ;AN000; + ;AN000; + mov ax,6 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + +; mov cx,len_append_assign_msg; length of string +; lea dx,append_assign_msg +; call print_STDERR ; display error message + jmp conflict_exit ; @@01 + ; @@01 +check_Topview: ; @@01 + mov bx,0 ; incase not there ; @@01 + mov ax,10h*256+34 ; TopView version check ; @@01 + int 15h ; @@01 + cmp bx,0 ; @@01 + jnz TopView_there ; @@01 + jmp replace_vector ; TopView has not been loaded, ; @@01 + ; @@01 +; TopView has been loaded before APPEND, bad news! ; @@01 + ; @@01 +TopView_there: ; @@01 +; mov cx,len_append_TV_msg ; length of string ; @@01 +; lea dx,append_TV_msg ; @@01 +; call print_STDERR ; display error message ; @@01 + call sysloadmsg ;AN000; + ;AN000; + mov ax,7 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + + ; @@01 +conflict_exit: ; @@01 + call ctrl_break_rest + mov al,0fdh ; @@05 + call terminate ; exit to DOS ; @@05 + +; get pointer to dir list, on return ES:DI points to buffer + +already_there: + +; This code has been moved to main_begin ; @@07 +; ; @@07 +; make sure the right version of APPEND has been loaded ; @@07 +; + +; mov dx,0 ; set for network version ; @@07 +; mov ah,append_2f ; int 2F function code for append ; @@07 +; mov al,DOS_version ; function code for get version ; @@07 +; int int_function ; @@07 +; cmp dx,word ptr version_loc ; does the version match? ; @@07 +; jump NE,bad_append_ver ; no, cough up an error messsage ; @@07 + +process_args: ; process all arguments + +;------------------------------------------------------------------- + mov si,0081h ; DS:SI points to argument area + mov cs:byte ptr e_switch+9,0 ; turn /E switch off + +process_argsx: ; process all arguments +; + + +; make sure that the /PATH and /X switches are re-enabled, and +; various flags are cleared + + mov ah,"/" + mov cs:byte ptr x_switch+9,ah ; re-enable /X switch + mov cs:byte ptr path_switch+9,ah ; re-enable /PATH switch + mov cs:byte ptr x_result.$P_Type,0 ; clear flag + mov cs:byte ptr path_result.$P_Type,0 ; clear flag + mov cs:byte ptr dirs_result.$P_Type,0 ; clear flag + mov cs:parse_flag,0 ; clear parse flag + +; set up things to call PARSER + + push cs ; make sure ES points to segment where + pop es ; parm block info is + lea di,cs:p_block2 ; ES:DI points to parm block, for secondary parsing + + + xor cx,cx ; ordinal value, must start as 0 + xor dx,dx ; must be 0 + + call Scan_For_Equal ; yes - let's see if we have "=" symbol ;an008; dms; + ; parse past it if we do + +get_pars_info: + call dword ptr pars_off ; call to COMMAND.COM's parser + + cmp ax,-1 ; end of line? + jne not_end_of_line ; no, carry on + jmp end_of_line_reached ; yes, go figure out what we got + +not_end_of_line: + + cmp ax,0 ; no, find out if there an error + je not_parse_error ; no, carry on + jmp parse_error ; yes, go display the error message + +; got here without any errors, set the proper bits in mode_flags + +not_parse_error: + mov cs: parse_flag,0ffh ; set parse flag + + +check_e: + cmp e_result.$P_Type,3 ; was there a /E in this pass? + jne check_x ; no, look for an X + + mov byte ptr e_switch+9,0 ; turn this off so we don't allow another + mov e_result.$P_Type,0 ; clear this so we don't get fooled later + + or mode_flags,E_mode ; set E mode on + + jmp get_pars_info ; go get another argument + +check_x: + cmp x_result.$P_Type,3 ; was there a /X on this pass? list index + je set_x ; yes, and it was /X w/o ON or OFF + + cmp x_result.$P_Type,2 ; was there a /X on this pass? list index + jne check_path + + mov byte ptr x_switch+9,0 ; turn this off so we don't allow another + mov x_result.$P_Type,0 ; clear this so we don't get fooled later + + cmp x_result.$P_Item_Tag,1 ; was /X or /X:ON specified? + je set_x ; yes, set X mode on + and mode_flags,NOT x_mode ; no, clear it + jmp get_pars_info + +set_x: + or mode_flags,x_mode + jmp get_pars_info + +check_path: + cmp path_result.$P_Type,2 ; was there a /path on this pass? list index + jne check_dirs + + xor ah,ah ; turn this off so we don't allow + mov byte ptr path_switch+9,ah ; another + mov path_result.$P_Type,0 ; clear this so we don't get fooled later + + + cmp path_result.$P_Item_Tag,1 ; was /PATH:ON specified? + je set_path ; yes, set PATH mode + and mode_flags,NOT path_mode ; no, clear it + jmp get_pars_info + +set_path: + or mode_flags,path_mode ; set PATH mode on + jmp get_pars_info + +; find out if dirs specified + +check_dirs: + cmp dirs_result.$P_Type,3 ; was a simple string returned? + je check_dirs2 ; yes, carry on + jmp get_pars_info ; no, all done for now + +; set up stuff to do the dirs copy + +check_dirs2: + push es + push ds + push si + push di + + lds si,dword ptr dirs_result.$P_Picked_Val ; get pointer to dirs string + mov dirs_result.$P_Type,0 ; clear this so we don't get fooled later + + mov di,0 ; set incase int 2f not installed ; @@08 + mov es,di ; @@08 + mov ax,append_2f*256+dir_ptr ; es:di -> internal result area ; @@08 + int int_function ; @@08 + mov ax,es ; see if active yet ; @@08 + or ax,di ; @@08 + jnz copy_dirs_loop ; ok, do the copy ; @@08 + push cs ; not active, set myself ; @@08 + pop es ; @@08 + lea di,app_dirs ; @@08 + +copy_dirs_loop: + movs es: byte ptr[di],ds:[si]; copy char + + cmp byte ptr ds:[si-1],0 ; is char a null + je done_copy_dirs + + jmp copy_dirs_loop + +done_copy_dirs: + + pop di + pop si + pop ds + pop es + + jmp get_pars_info ; no error yet, loop till done + +end_of_line_reached: + mov old_syntax,0 ; process old format operands + + cmp cs:initial_pass,-1 ; is this the first APPEND ;AN006; + je first_one ; yes, clear flag and exit ;AN006; + + cmp cs:parse_flag,0 ; if this flag is off, means null command line + ; was nothing on the command line + je display_dirs ; go display the dirs + +first_one: ;AN006; + mov cs:initial_pass,0 ; clear first pass flag ;AN006; + +done_for_now: +normal_exit: + call ctrl_break_rest ; reset control break checking + mov ax,0 ; set string + ret ; exit to COMMAND + + +parse_error: + push ax ;save parser error code ;an010;bgb + call sysloadmsg ;AN000; + pop ax ;restore parser error coed ;an010;bgb + call do_parse_err ;an010;bgb + jmp bad_parmx ; display message and get out + +;------------------------------------------------------------------- + +; mov si,0081h ; point si to argument area +; mov bx,ss +; mov ds,bx +; +;process_argsx: ; process all arguments +; mov di,0 ; set incase int 2f not installed ; @@08 +; mov es,di ; @@08 +; mov ax,append_2f*256+dir_ptr ; es:di -> internal result area ; @@08 +; int int_function ; @@08 +; mov ax,es ; see if active yet ; @@08 +; or ax,di ; @@08 +; jnz have_ptr ; @@08 +; push cs ; not active, set myself ; @@08 +; pop es ; @@08 +; lea di,app_dirs ; @@08 +;have_ptr: ; @@08 +; +;; step through the DOS command line argument area, and copy the new dir +;; list to the proper place in APPEND. This requires some parsing for +;; spaces, tabs chars, equal signs, as well as conversion to upper case +; +; cmp byte ptr[si],"=" ; APPEND=path is OK syntax +; jne skip_leading +; inc si +;skip_leading: ; skip leading spaces +; lodsb +; cmp al," " +; je skip_leading +; cmp al,tab_char +; je skip_leading +; cmp al,"," ; @@15 +; je skip_leading ; @@15 +; cmp al,"=" ; @@15 +; je skip_leading ; @@15 +; cmp al,cr ; did we have command line arguments? +; jump E,display_dirs ; no, display the dirs currently appended +; cmp al,"/" ; is it a parm starter? ; @@05 +; jump E,bad_path_parm ; yes, it's an error ; @@05 +; dec si +; +;copy_args: +; lodsb ; get char from command line area +; cmp al,cr ; are we at the end? +; jump E,found_end ; yes, display the currently appended dirs +; cmp al," " ; is it a space? +; je found_space ; yes, at end +; cmp al,tab_char ; is it a tab? +; je found_space ; yes, treat it like a space +; cmp al,"/" ; is it a parm starter? +; je bad_path_parm ; yes, it's an error ; @@05 +; cmp al,"a" ; find out if we have a lower case char +; jb copy_char ; @@14 +; cmp al,"z" +; ja copy_char ; @@14 +; sub al,"a"-"A" ; convert char to upper case ; @@14 +; +;copy_char: +; mov in_middle,-1 ; say that we made it to the middle +; stosb ; no, copy char into resident storage area +; jmp copy_args ; do it some more +; +;found_space: +; cmp in_middle,0 ; set the space flag then go through +; jump E,copy_args ; loop some more +; +;found_end: +; cmp in_middle,0 ; if I found the end of string but not +; jump E,display_dirs ; in the middle, go display some dirs +; +; mov es:byte ptr [di],0 ; null terminate the string +; mov in_middle,0 +; cmp al,cr +; je past_trailing +; +;skip_trailing: ; skip end spaces +; lodsb +; cmp al," " +; je skip_trailing +; cmp al,tab_char +; je skip_trailing +; cmp al,"/" ; path and parm not together ; @@05 +; je bad_path_parm ; @@05 +; cmp al,cr ; only white space allowed at end +; jne bad_path +;past_trailing: +; +; cmp old_syntax,0 ; go back to normal mode +; je normal_exit +; jmp exit_append2 +;normal_exit: +; call ctrl_break_rest ; reset control break checking +; mov ax,0 ; set string +; ret ; exit to COMMAND + +bad_path: ; bad paath operand +; mov cx,len_path_error_msg ; length of string +; lea dx,path_error_msg + call sysloadmsg ;AN000; + ;AN000; + mov ax,3 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; +;gga call sysdispmsg ;AN000; + + jmp short bad_parmx + +bad_path_parm: ; bad parameter ; @@05 +; mov cx,len_path_parm_error_msg ; length of string ; @@05 +; lea dx,path_parm_error_msg ; @@05 + call sysloadmsg ;AN000; + mov ax,3 ; message number ;AN000; + mov bx,STDERR ; standard error ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + jmp short bad_parmx ; @@05 +bad_parm: ; bad parameter +; mov cx,len_parm_error_msg ; length of string +; lea dx,parm_error_msg + call sysloadmsg ;AN000; + ;AN000; + mov ax,3 ; message number ;AN000; + mov bx,STDERR ; standard error ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + +bad_parmx: ; bad parameter + push ds + push cs + pop ds +; call print_STDERR ; display error message + lea si,inv_parm ; point to msg parm ;an010;bgb + call sysdispmsg ;AN000; + pop ds + call ctrl_break_rest + mov al,1 ; @@05 + call terminate ; exit to DOS ; @@05 + +; This code has been moved to main_begin ; @@07 +;bad_append_ver: ; append version mismatch ; @@07 +; push ds ; @@07 +; push cs ; @@07 +; pop ds ; @@07 +; mov cx,len_bad_append_msg ; @@07 +; lea dx,bad_append_msg ; bad app message ; @@07 +; call print_STDERR ; @@07 +; lea dx,crlf ; carriage return, line feed ; @@07 +; mov cx,crlf_len ; length of string ; @@07 +; call print_STDERR ; @@07 +; pop ds ; @@07 +; call ctrl_break_rest ; @@07 +; mov ax,0feh ; bad APPEND version ; @@05 +; call terminate ; exit to DOS ; @@05 + +; Display currently appended directories + +display_dirs: + call address_status ; get working path ; @@03 + push ds + push es + pop ds + + cmp es:byte ptr[di],";" ; no append now + je no_dirs_appended + +; count the chars in the dir list, cx will hold the count + + mov si,di + sub si,6+1 ; move pointer to APPEND + mov dx,si ; save pointer to string + xor cx,cx + +scanit: + lodsb ; get character + cmp al,null ; are we at end? + je print_it ; yes, print it + inc cx ; look at the next character + jmp scanit ; loop till we find the end + +print_it: + call print_STDOUT ; display appended dirs + push cs + pop ds + lea dx,crlf ; carriage return, line feed + mov cx,crlf_len ; length of string + call print_STDOUT + pop ds + +exit_append: + cmp old_syntax,0 ; process old format operands + je exit_append2 + mov si,0081h ; set up rescan + mov ah,get_PSP + call int_21 + mov ds,bx + jmp process_argsx + +exit_append2: + mov old_syntax,0 ; after first time this must be off + call ctrl_break_rest ; reset control break checking + mov ax,-1 ; no action + ret ; exit to COMMAND + +no_dirs_appended: + push cs + pop ds + + call sysloadmsg ;AN000; + ;AN000; + mov ax,5 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + +; lea dx,no_append_msg ; no dirs message ;AN000; +; mov cx,len_no_append_msg ; length of string ;AN000; +; call print_STDOUT ;AN000; + pop ds + jmp exit_append2 ; APPEND = = fix ;GGA + +page +;------------------------------------------------------------------- +; Getting here means that APPEND has not been loaded yet. Get the +; old vector, save it, and point the vector to the new routine. +;------------------------------------------------------------------- + +replace_vector: + + push ds + mov si,0081h ; point si to argument area + mov ah,get_PSP + call int_21 + mov ds,bx + +; Process /X and /E parameters + +skip_leading2: ; skip leading spaces +; lodsb +; cmp al," " +; je skip_leading2 +; cmp al,tab_char +; je skip_leading2 +; cmp al,cr ; at end +; jump E,parms_done +; cmp al,"/" +; jne set_old_syntax + +found_slash: +; lodsb +; cmp al,"e" +; je slash_E +; cmp al,"E" +; je slash_E +; cmp al,"x" +; je slash_X +; cmp al,"X" +; je slash_X +bad_parmy: +; pop ds +; jmp bad_parm +bad_path_parmy: +; pop ds +; jmp bad_path_parm + +slash_X: +; test mode_flags,X_mode ; no duplicates allowed +; jnz bad_parmy +; or mode_flags,X_mode +; jmp short slashx + +slash_E: +; test mode_flags,E_mode ; no duplicates allowed +; jnz bad_parmy +; or mode_flags,E_mode +slashx: +; jmp skip_leading2 ; loop some more +set_old_syntax: +;; test mode_flags,0 ; no /? switches on old mode +;; jne bad_path_parmy + mov old_syntax,1 +parms_done: + pop ds + jmp exit_append +page + +set_vectors: ; set append hooks ; @@05 + push es + +; Get INT 2f vector. Save to call older 2f handlers + + mov ax,get_intfcn ; Get INT 2fh vector + call int_21 + mov intfcn_offset,bx ; Save it + mov intfcn_segment,es + +; get int 21 vector + + mov ax,get_vector ; Get INT 21h vector + call int_21 + mov vector_offset,bx ; Save it + mov vector_segment,es + pop es + + push ds ; @@08 + push cs ; @@08 + pop ds ; @@08 + lea dx,intfcn_hook ; DS:DX = New INT 2fh vector + mov ax,set_intfcn ; Hook the interrupt + call int_21 + + lea dx,interrupt_hook ; DS:DX = New INT 21h vector + mov ax,set_vector ; Hook the interrupt + call int_21 + + mov dirlst_segment,cs ; save the address of the dirlist + lea dx,app_dirs + mov dirlst_offset,dx + pop ds ; @@08 + + ret ; @@05 + +terminate: ; terminate to dos or return ; @@05 + cmp res_append,0 ; @@05 + jne is_res ; @@05 + call Release_Environment ; release environmental vector ;ac009; dms; + mov ah,term_proc ; return to DOS on first time ; @@05 + call int_21 ; @@05 +is_res: ; @@05 + mov ax,-1 ; set abort requested ; @@05 + jmp abort_exit ; must go back to COMMAND ; @@05 + + +print_STDOUT: + mov bx,STDOUT ; Standard output device handle + mov ah,awrite ; function code for write + call int_21 + ret + +print_STDERR: + mov bx,STDERR ; Standard output device handle + mov ah,awrite + call int_21 + ret + +Release_Environment: ;an007; dms; + + push ax ;save regs ;an007; dms; + push bx ; ;an007; dms; + push es ; ;an007; dms; + mov ah,Get_PSP ; get the PSP segment ;an007; dms; + call int_21 ; invoke INT 21h ;an007; dms; + mov es,bx ; BX contains PSP segment - put in ES ;an007; dms; + mov bx,word ptr es:[PSP_Env]; get segment of environmental vector ;an007; dms; + mov es,bx ; place segment in ES for Free Memory ;an007; dms; + mov ah,Free_Alloc_Mem ; Free Allocated Memory ;an007; dms; + int 21h ; invoke INT 21h ;an007; dms; + pop es ; restore regs ;an007; dms; + pop bx ; ;an007; dms; + pop ax ; ;an007; dms; + + ret ; return to caller ;an007; dms; + +;========================================================================= +; Scan_For_Equal : This routine scans the command line from the +; beginning until it encounters anything other +; than the equal, tab, or space characters. +; Register SI is sent back to the caller pointing +; to the character that does not meet the match +; criteria. +; +; Inputs : DS:SI - pointer to next parm +; +; Outputs : SI - adjusted to byte not matching the following: +; "=" +; " " +; TAB +; +; Author : DS +; Date : 1/27/88 +; Version : DOS 3.4 +;========================================================================= + +Scan_For_Equal: + + push ax ; save regs ;an008; dms; + push cx ; ;an008; dms; + + xor cx,cx ; clear cx ;an008; dms; + mov cl,byte ptr ds:[80h] ; get length of command line ;an008; dms; + +Scan_For_Equal_Loop: + + cmp cx,0 ; at end? ;an008; dms; + jbe Scan_For_Equal_Exit ; exit loop ;an008; dms; + mov al,byte ptr ds:[si] ; get 1st. character ;an008; dms; + call Chk_DBCS ; DBCS lead byte? ;an008; dms; + jnc Scan_For_Equal_No_DBCS ; no ;an008; dms; + cmp byte ptr ds:[si],81h ; blank lead byte ;an008; dms; + jne Scan_For_Equal_Exit ; exit with adjusted SI ;an008; dms; + cmp byte ptr ds:[si+1],40h ; DBCS blank ;an008; dms; + jne Scan_For_Equal_Exit ; exit with adjusted SI ;an008; dms; + + add si,2 ; yes - DBCS lead byte ;an008; dms; + sub dx,2 ; decrease counter ;an008; dms; + jmp Scan_For_Equal_Loop + +Scan_For_Equal_No_DBCS: + + cmp al,"=" ; = found? ;an008; dms; + je Scan_For_Equal_Next ; next character ;an008; dms; + cmp al,20h ; space? ;an008; dms; + je Scan_For_Equal_Next ; next character ;an008; dms; + cmp al,09h ; tab? ;an008; dms; + je Scan_For_Equal_Next ; next character ;an008; dms; + jmp Scan_For_Equal_Exit ; exit with adjusted SI ;an008; dms; + +Scan_For_Equal_Next: + + inc si ; adjust ptr ;an008; dms; + dec cx ; decrease counter ;an008; dms; + jmp Scan_For_Equal_Loop ; continue loop ;an008; dms; + +Scan_For_Equal_Exit: + + pop cx ; ;an008; dms; + pop ax ; ;an008; dms; + + ret ; return to caller ;an008; dms; + + + +;========================================================================= ;an010;bgb +; do_parse_err : This routine sets up for the display of a parse ;an010;bgb +; error, and displays the offending parameter. ;an010;bgb +; ;an010;bgb +; Inputs : DS:SI - points just past offending parm in command line ;an010;bgb +; ;an010;bgb +; Outputs : si_off- parm for msg ret. ;an010;bgb +; si_seg- parm for msg ret. ;an010;bgb +; command line - hex zero at end of offending parm ;an010;bgb +; ;an010;bgb +; Date : 3/29/88 ;an010;bgb +; Version : DOS 4.0 (wow!) ;an010;bgb +;========================================================================= ;an010;bgb +do_parse_err PROC ;an010;bgb +;;;;;;;;mov ax,3 ;removed- parser handles this ;an010;bgb + mov bx,STDERR ; handle ;an010;bgb +;;;;;;;;xor cx,cx ; sub count ;an010;bgb + mov cx,1 ;display invalid parm ;an010;bgb + xor dl,dl ; no input ;an010;bgb + mov dh,02 ; message class of parse error ;an010;bgb +;;;;;;;;mov cs:si_off,81h ;initialize pointer ;an010;bgb + ;an010;bgb + dec si ;point to last byte of invalid parm ;an010;bgb +public decsi ;an010;bgb +decsi: cmp byte ptr [si],' ' ;are we pointing to a space? ;an010;bgb +; $IF E,OR ;if so, we dont want to do that ;an010;bgb + JE $$LL1 + cmp byte ptr [si],0dh ;are we pointing to CR? ;an010;bgb +; $IF E ;if so, we dont want to do that ;an010;bgb + JNE $$IF1 +$$LL1: + dec si ;find the last byte of parm ;an010;bgb + jmp decsi ;an010;bgb +; $ENDIF ;an010;bgb +$$IF1: + mov byte ptr [si+1],00 ;zero terminate display string ;an010;bgb +nextsi: ;an010;bgb +public nextsi ;an010;bgb + dec si ;look at previous char ;an010;bgb + cmp byte ptr [si],' ' ;find parm separator ;an010;bgb + jnz nextsi ;loop until begin of parm found ;an010;bgb + ;an010;bgb + mov cs:si_off,si ;mov si into display parms ;an010;bgb + mov cs:si_seg,ds ;initialize pointer ;an010;bgb + ret ; return to caller ;an010;bgb +do_parse_err ENDP ;an010;bgb + + +;------------------------------------------------------------------- +; +;------------------------------------------------------------------- + +MSG_SERVICES +MSG_SERVICES + +end_address: ; this is the end of the TSR stuff ;AN004; + +include parse.asm ; include the parser code +include msgdcl.inc + +cseg ends +sseg segment para stack 'STACK' + assume ss:sseg + dw 512 dup(0) +mystack dw 0 +sseg ends + + + + end main_begin + \ No newline at end of file -- cgit v1.2.3