home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcmagazi
/
1990
/
16
/
install.asm
< prev
next >
Wrap
Assembly Source File
|
1990-06-28
|
20KB
|
716 lines
; INSTALL.ASM
; (c) 1989, 1990 Ashok P. Nadkarni
;
; This code is the installation code for CMDEDIT. This file must be
; linked last !
INCLUDE common.inc
INCLUDE ascii.inc
INCLUDE dos.inc
INCLUDE general.inc
PUBLIC install_begin
PUBLIC install
PUBLIC file_error
PUBLIC abort_install
PUBLIC dirstk_error
PUBLIC process_args
CSEG SEGMENT PARA PUBLIC 'CODE'
EXTRN getargs:PROC
EXTRN cmdlen:BYTE
EXTRN default_imode:BYTE
EXTRN auto_recall:BYTE
EXTRN pgm_name:BYTE
EXTRN silent:BYTE
EXTRN macrosize:WORD
EXTRN macro_ignore_char:BYTE
EXTRN symsize:WORD
EXTRN dossize:WORD
EXTRN dirsize:WORD
EXTRN mfilename:BYTE
EXTRN mfile_seen:BYTE
EXTRN prev_isr1b:WORD
EXTRN enable_dircmds:BYTE
EXTRN dos_version_major:BYTE
EXTRN dos_version_minor:BYTE
EXTRN old_int21vec:WORD
EXTRN cmdedit:PROC
EXTRN our_break_handler:PROC
EXTRN init_over:PROC
EXTRN cmdedit_isr:PROC
DGROUP GROUP CSEG
ASSUME CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
; install_begin MUST be start of installation code.
install_begin LABEL BYTE
msg_nomem db '* Insufficient Memory - Reduce buffer sizes *',CR,LF,DOLLAR
option_error db '* Unknown or illegal options *',CR,LF,DOLLAR
file_error db '* Error processing command file *',CR,LF,DOLLAR
dirstk_error db '* Error processing directory stack commands *',CR,LF,DOLLAR
inv_dosver db '* Unsupported DOS version. *',CR,LF,DOLLAR
msg_dup db '* CMDEDIT already installed in memory. *',CR,LF,DOLLAR
options_dup db '* Only options /g /i /r /p may be specified. *',CR,LF,DOLLAR
msg_notdup db '* No copy of CMDEDIT found in memory. *',CR,LF,DOLLAR
msg_unload db '* Unable to unload CMDEDIT. *',CR,LF
db '* Uninstall TSRs in reverse order. *',CR,LF,DOLLAR
msg_memerr db '* DOS memory allocation error! *',CR,LF,BEL
db '* Recommend you reboot! *',CR,LF,BEL,DOLLAR
msg_uninstalled db '* CMDEDIT uninstalled successfully *',CR,LF,DOLLAR
msg_omode db '* Default overwrite mode enabled. *',CR,LF,DOLLAR
msg_imode db '* Default insert mode enabled. *',CR,LF,DOLLAR
msg_enable_autorecall db '* CMDEDIT autorecall enabled. *',CR,LF,DOLLAR
msg_disable_autorecall db '* CMDEDIT autorecall disabled. *',CR,LF,DOLLAR
msg_enable_bell db '* CMDEDIT error bell enabled. *',CR,LF,DOLLAR
msg_disable_bell db '* CMDEDIT error bell disabled. *',CR,LF,DOLLAR
msg_ignore_char db '* CMDEDIT ignore character changed. *',CR,LF,DOLLAR
cmdedit_seg dw 0 ;Segment of the first copy
; of CMDEDIT loaded into memory.
argflags db 0 ;Used to remember what args have been seen.
dosarg equ 1
applarg equ 2
filearg equ 4
dirarg equ 8
macroarg equ 16
symarg equ 32
uninstall_arg equ 64
ignore_arg equ 128
argument_buffer db LINEBUF_SIZE DUP (?)
; This location is jumped to when the program is run from the DOS
; command line. The program parses the input line, takes
; appropriate actions, initializes buffers etc. and then TSR's
; after taking over interrupt 21h. The memory taken up by the ISEG
; segment will then be used for various data buffers since this
; code is no longer needed.
install proc near
cld ;Entire program assumes direction flag will
; be cleared
ASSUME CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
@DispStr pgm_name ;Display program name
; Make sure we are running DOS 2.x or higher
call near ptr get_dosversion
cmp dos_version_major,1 ;DOS 1.x ?
jne @install_1
@DispStr inv_dosver
mov ax,-1
jmp abort_install ;V1.x not supported.
@install_1:
; Locate the segment of the first copy of CMDEDIT in memory so that
; we can tell if this is a second copy.
call near ptr locate_cmdedit
mov cmdedit_seg,ax ;Remember it
@install_5:
mov si,offset cmdlen ;
lodsb ;SI == line in PSP, AL == line length
mov cl,al
xor ch,ch ;CX = line length
xor ax,ax ;Function = get argument count
push cx ;Save line length
call near ptr getargs ;AX := # arguments in command line
pop cx ;Restore line length
mov di,ax ; DI == number of arguments
inc di ;Prime for loop
@install_10:
dec di ;Any more arguments ?
jz @install_20 ;No
mov bx,offset DGROUP:argument_buffer
mov dx,SIZE argument_buffer
mov ax,di ;Argument number
push cx ;save line length
call near ptr getargs ;Get argument into argument_buffer
; (no chance of buffer being too short)
call near ptr process_args ;Process the argument
pop cx ;Restore line length
jmp short @install_10 ;loop back to process remaining args
@install_20:
; OK now we have done all necessary parsing without errors. Now first check
; if the uninstall option was specified.
test argflags,uninstall_arg
je @install_21 ;Nope
; We have to unload a previously installed copy of CMDEDIT. See if it is
; really there.
mov ax,ds ;Are we the only copy of CMDEDIT ?
cmp ax,cmdedit_seg
je @install_20_a ;There is no other copy
jmp uninstall
@install_20_a:
@DispStr msg_notdup ;Indicate no copy to uninstall
mov ax,-1
jmp abort_install ;Exit
@install_21:
; No uninstall option specified. Now check if this is the only copy of
; CMDEDIT.
mov ax,ds
cmp ax,cmdedit_seg
je @install_21_a ;We are the only copy. Proceed with
; installation
jmp change_installed_options ;Else go change installed options.
@install_21_a:
; At this point all the arguments have been parsed. Now check
; that the sum total of the various buffer sizes does not exceed
; segment limits. Also check for mandatory minimum sizes.
; Finally, transfer control to the resident portion which will
; relocate buffers to overlay the installation code.
mov ax,OFFSET DGROUP:install_begin
;add starting address where buffers
; will begin
add ax,STACK_SIZE
jnc @install_23
jmp @install_125
@install_23:
cmp macrosize,MACROSIZE_MIN
jnb @install_22
mov macrosize,MACROSIZE_MIN ;Ensure min buffer sizes
@install_22:
add ax,macrosize
jc @install_125
cmp symsize,SYMSIZE_MIN
jnb @install_24
mov symsize,SYMSIZE_MIN ;Ensure min buffer sizes
@install_24:
add ax,symsize
jc @install_125
cmp dossize,DOSSIZE_MIN
jnb @install_26
mov dossize,DOSSIZE_MIN ;Ensure min buffer sizes
@install_26:
add ax,dossize
jc @install_125
cmp dirsize,DIRSIZE_MIN
jnb @install_30
mov dirsize,DIRSIZE_MIN ;Ensure min buffer sizes
@install_30:
add ax,dirsize
jc @install_125
;Enough memory, so keep resident. Install our Ctrl-Break handler.
push es ;Save ES
mov ah,35h
mov al,1bh ;Ctrl-Break Interrupt
int 21h ;Get current handler address
mov CS:prev_isr1b,bx ;Offset of previous handler
mov CS:prev_isr1b+2,es ;Segment of previous handler
pop es ;Restore es
mov dx,offset CS:our_break_handler
push ds ;Save DS
mov ax,cs
mov ds,ax ;DS:DX->our break handler
mov al,1bh
mov ah,25h ;Set up our break handler
int 21h
pop ds ;Restore DS
;
jmp near ptr init_over
@install_125:
@DispStr msg_nomem
mov ax,-1
jmp abort_install
install endp
;+
; FUNCTION : process_args
;
; Processes the argument pointed to by BX. AX contains length
; of argument. If a previously seen argument is repeated, it is
; ignored (ie. the old value is kept). Note that the argument is
; assumed not to contain any delimiters (like space or tab).
;
; Options start with either a '-' or '/'. Any associated value must
; follow immediately after without any intervening space/tab.
; /f Macro file to be read.
; /d DOS history buffer size
; /a Application history buffer size (only if
; separate histories maintained) (OUTDATED)
; /m Macro buffer size
; /b symbol buffer size
; /s Directory Stack size
; /r Auto recall mode
; /i Insert mode default
; /g Silent mode
; /p macro ignore character
; /e Enable dir commands all the time (OUTDATED)
; /u Uninstall CMDEDIT
;
; Invalid options result in program abortion. If an option is not
; followed by a value, the default value for the option is assumed.
;
; Note that this is NOT a general purpose getopt type routine.
;
; Parameters:
; BX = Pointer to argument
; AX = Number of characters in argument
;
; Returns:
; Nothing.
; Various globals may be set according to the specified argument.
; Register(s) BX (call to aton),CX are destroyed.
;-
process_args proc near
@save si,di
test argflags,uninstall_arg
jne @process_args_5 ;If /U specified, no other arg is allowed
xchg ax,cx ;CX = character count
sub cx,2 ;Delete switch char and option letter
jb @process_args_5 ;Error in option specification
; if num chars less than 2
mov si,bx ;SI = arg buffer address
lodsb ;AL = first character
cmp al,'/' ;Should be either '/'
je @process_args_10 ;
cmp al,'-' ; or '-'
jne short @process_args_5 ;Else error
@process_args_10: ;Saw a valid switch char
lodsb ;AL = option letter
or al,32 ;Lowercase (non alphabetic will be
; ignored anyway)
cmp al,'u' ;Uninstall option ?
jne @process_args_11_a ;No
or cx,cx ;Ok if no more chars in arg
jne short @process_args_5 ;Else error
@process_args_11:
or argflags,uninstall_arg ;Indicate /U seen
jmp @process_args_50 ;Return
@process_args_11_a:
cmp al,'i' ;insert mode option ?
jne @process_args_14 ;No
jcxz @process_args_12 ;Ok if no more chars in arg
@process_args_5:
; Error processing
@DispStr option_error
mov ax,-1
jmp abort_install
@process_args_12:
mov default_imode,1 ;Change default insrt mode
jmp @process_args_50 ;Return
@process_args_14:
cmp al,'g' ;silent mode option ?
jne @process_args_15 ;No
jcxz @process_args_14_a ;Ok if no more chars in arg
jmp short @process_args_5 ;Else error
@process_args_14_a:
mov silent,1 ;Silent mode
jmp @process_args_50 ;Return
@process_args_15:
cmp al,'r' ;auto-recall option ?
jne @process_args_18 ;No
jcxz @process_args_16 ;Ok if no more chars in arg
jmp short @process_args_5 ;Else error
@process_args_16:
mov auto_recall,1 ;Set auto-recall mode
jmp @process_args_50 ;Return
@process_args_18:
cmp al,'e' ;Enable dir commands option?
jne @process_args_18_b ;No
jcxz @process_args_18_a ;OK if no more chars
jmp short @process_args_5 ;Else error
@process_args_18_a:
mov enable_dircmds,1 ;enable directory commands
jmp @process_args_50 ;Return
@process_args_18_b:
cmp al,'p' ;ignore character option
jne @process_args_19
cmp cx,1 ;Should be only one more char
jne @process_args_5 ;Error
lodsb
or argflags,ignore_arg ;Indicate that an ignore char set
mov macro_ignore_char,al
jmp @process_args_50 ;Return
@process_args_19:
cmp al,'f' ;Is it the macro file option ?
jne @process_args_20
test argflags,filearg ;Already seen file argument ?
je @process_args_19_a ;No, then update
jmp @process_args_50 ;Yes, then don't update
@process_args_19_a:
or argflags,filearg ;Remember we've seen this option
jcxz @process_args_50 ;If 0 count, no file to be read
cmp cx,63 ;Max path length must be < 64
ja @process_args_5 ;Error
mov di,offset mfilename ;Temp storage for filename
rep movsb ;Copy file name
mov byte ptr [di],0 ;Terminate with a NULL char
mov mfile_seen,1 ;Indicate that init file specified
jmp short @process_args_50
@process_args_20:
push ax ;Save the option letter
xchg ax,cx ;AX = num of char
call near ptr aton ;All other options are numeric values
jnc @process_args_22 ;No Errors
jmp @process_args_5 ;Error
@process_args_22:
;AX contains numeric value
xchg ax,cx ;CX = numeric value
pop ax ;Restore option letter
cmp al,'d' ;Is it the dos history size option ?
jne @process_args_25
test argflags,dosarg ;Already seen argument ?
jne @process_args_50 ;Yes, then don't update
or argflags,dosarg ;Remember we've seen this option
mov dossize,cx
jmp short @process_args_50
@process_args_25:
cmp al,'m' ;Is it the macro buf size option ?
jne @process_args_35
test argflags,macroarg ;Already seen argument ?
jne @process_args_50 ;Yes, then don't update
or argflags,macroarg ;Remember we've seen this option
mov macrosize,cx
jmp short @process_args_50
@process_args_35:
cmp al,'b' ;Is it the symbol buf size option ?
jne @process_args_40
test argflags,symarg ;Already seen argument ?
jne @process_args_50 ;Yes, then don't update
or argflags,symarg ;Remember we've seen this option
mov symsize,cx
jmp short @process_args_50
@process_args_40:
cmp al,'s' ;Is it the dir stack option ?
je @process_args_55 ;Yes
jmp @process_args_5 ;Invalid arg
@process_args_55:
test argflags,dirarg ;Already seen argument ?
jne @process_args_50 ;Yes, then don't update
or argflags,dirarg ;Remember we've seen this option
mov dirsize,cx
@process_args_50:
@restore
ret
process_args endp
;+
; FUNCTION : aton
;
; Returns the positive integer value of an ASCII string. The value
; must be between 0 and 65535. If length of string is 0, then a 0
; value is returned with no error flags.
;
; Parameters:
; SI := address of first character in string
; AX := count of characters
;
; Returns:
; AX = 16 bit result if no errors.
; CF = 1 if error (magnitude too large, invalid character etc.)
; 0 if no errors.
; Register(s) CX,DX are destroyed.
;-
aton proc near
@save si,di
xor di,di ;Result
xchg ax,cx ;CX <- num of chars
jcxz @aton_99 ;No chars, result = 0 (CF is also 0)
cmp cx,6 ;Shouldn't be more'n 5 chars
cmc ;CF=1 if error
jb @aton_99 ;Error exit
@aton_10:
lodsb ;al = char
sub al,'0' ;Is ASCII value < '0'
jb @aton_99
mov dx,9 ;Comparison with 9, NOT '9'
cmp dl,al
jb @aton_99 ;Not valid char
xor ah,ah
inc dx ;DX = 10 (multiplier)
xchg ax,di ;ax = result so far
mul dx ;Multiply by 10
jb @aton_99 ;Overflow
add ax,di ;Add new character
jb @aton_99 ;Overflow
xchg ax,di ;Remember new result in di
loop @aton_10 ;Go onto next char
@aton_99:
xchg ax,di
@restore
ret
aton endp
;+
; FUNCTION : get_dosversion
;
;
; Stores DOS major and minor versions in dos_version_major and
; dos_version_minor.
;-
get_dosversion proc near
mov ah,30h
int 21h
mov dos_version_major,al
mov dos_version_minor,ah
ret
get_dosversion endp
;+
; FUNCTION : abort_install
;
; Called to abort program before installation. Exits to DOS.
;
; Parameters:
; AL = Exit code
;
; Returns:
; Nothing.
;
; Register(s) destroyed:
; N/A
;-
abort_install proc near
@Exit
abort_install endp
;+
; FUNCTION : locate_cmdedit
;
; Called to locate the first copy of CMDEDIT loaded into memory. This
; is not foolproof in that if CMDEDIT is loaded into high memory
; using one of the memory managers like QEMM, it will not be found.
;
; Parameters:
; None.
;
; Returns:
; AX - segment of first copy of CMDEDIT in memory.
;
; Register(s) destroyed:
; <TBA>
;-
locate_cmdedit proc near
@save si,di,es
mov di,offset DGROUP:cmdedit ;SI and DI will used for
mov si,di ;comparisons
xor ax,ax ;AX will track segments
@locate_cmdedit_5:
mov es,ax
push si ;Save offsets that are
; compared
mov cx,32 ;Count to be matched
rep cmpsb
pop si ;Restore offsets that are
; compared
je @locate_cmdedit_50 ;Matched
mov di,si
inc ax
jmp short @locate_cmdedit_5 ;Try next segment
@locate_cmdedit_50:
@restore
ret
locate_cmdedit endp
;+
; FUNCTION : uninstall
;
; Called to uninstall a previously loaded copy of CMDEDIT.
; The routine does not return. It exits CMDEDIT.
;
; Parameters:
; None.
;
; Returns:
; None.
;
; Register(s) destroyed:
; <TBA>
;-
uninstall proc near
; Free up the memory occupied by the previous loaded copy of CMDEDIT.
; First give back the all interrupts that were taken over.
; Make sure no one else has taken over the 1b break handler since we
; took it over.
mov ax,351bh ;Retrieve current 1b handler
int 21h
cmp bx,offset our_break_handler ;Is the offset the ours ?
je @uninstall_20 ;Yes
@uninstall_10:
; Someone else's taken over the interrupt. Display message and exit.
@DispStr msg_unload
mov ax,-1
jmp abort_install
@uninstall_20:
mov ax,es ;Now compare segment
cmp ax,cmdedit_seg ;Is it what we expect?
jne @uninstall_10 ;No, display error
; Now check the int 21h handler.
mov ax,3521h ;Retrieve current 1b handler
int 21h
cmp bx,offset cmdedit_isr ;Is the offset the ours ?
jne @uninstall_10 ;No, error
mov ax,es ;Now compare segment
cmp ax,cmdedit_seg ;Is it what we expect?
jne @uninstall_10 ;No, display error
; OK, now restore both interrupts
mov es,cmdedit_seg ;ES<-segment of loaded CMDEDIT
mov dx,es:prev_isr1b ;DS:DX->original 1b handler
mov ds,es:prev_isr1b+2
mov ax,251bh ;Return int 1b
int 21h
mov dx,es:old_int21vec ;DS:DX->original int 21h handler
mov ds,es:old_int21vec+2
mov ax,2521h ;Return int 21
int 21h
push cs
pop ds ;Restore DS
;
; Finally, return the block of memory taken up by the previous CMDEDIT copy.
mov ah,49h ;Release block function, ES->segment
int 21h ;Free the block
jnc @uninstall_90 ;No errors
@DispStr msg_memerr ;Memory allocation error !
mov ax,-1
jmp abort_install
@uninstall_90:
@DispStr msg_uninstalled
xor ax,ax
@Exit 0 ;Exit to DOS
uninstall endp
;+
; FUNCTION : change_installed_options
;
; Called to change settings on a previously installed copy of
; CMDEDIT. The function exits to DOS.
;
; This function allows the following options to be toggled or
; changed:
; /r - toggles autorecall mode
; /i - toggles insert mode
; /g - toggles silent mode
; /p - sets a new ignore character
;
; If any other option is specified, error message is displayed.
;
; Parameters:
; None.
;
; Returns:
; Nothing.
;
; Register(s) destroyed:
; <TBA>
;-
change_installed_options proc near
@DispStr msg_dup
mov al,argflags
and al,NOT ignore_arg
je @change_installed_options_10
; Unallowed options specified.
@DispStr options_dup
mov ax,-1
jmp abort_install
@change_installed_options_10:
@DispCh LF
; Change the options specified.
mov es,cmdedit_seg ;ES->segment of previously loaded
; CMDEDIT
; First toggle the insert mode option. If /i specified, default_imode will
; be 1, else 0. Thus just xor it with the memory resident copy to toggle
; default mode.
mov al,es:default_imode
xor al,default_imode
mov es:default_imode,al ;Toggle memory resident option
or al,al
je @change_installed_options_15
@DispStr msg_imode
jmp short @change_installed_options_20
@change_installed_options_15:
@DispStr msg_omode
@change_installed_options_20:
mov al,es:auto_recall
xor al,auto_recall
mov es:auto_recall,al ;Toggle memory resident option
or al,al
jne @change_installed_options_25
@DispStr msg_disable_autorecall
jmp short @change_installed_options_30
@change_installed_options_25:
@DispStr msg_enable_autorecall
@change_installed_options_30:
; And now for silent mode
mov al,es:silent
xor al,silent
mov es:silent,al ;Toggle memory resident option
or al,al
je @change_installed_options_35
@DispStr msg_disable_bell
jmp short @change_installed_options_40
@change_installed_options_35:
@DispStr msg_enable_bell
@change_installed_options_40:
; Finally change the ignore character if one was specified.
test argflags,ignore_arg
je @change_installed_options_90 ;None specified
; Change to the new macro ignore char
mov al,macro_ignore_char
mov es:macro_ignore_char,al
@DispStr msg_ignore_char
@change_installed_options_90:
; All done
@Exit 0
change_installed_options endp
CSEG ENDS
END