home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mega CD-ROM 1
/
megacd_rom_1.zip
/
megacd_rom_1
/
DESQVIEW
/
CMONITOR.ZIP
/
CMONITOR.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-12-07
|
22KB
|
531 lines
TITLE CMONITOR
PAGE, 132
COMMENT |
Copyright by John Poindexter Rockville, MD
Version 1.3 December 7, 1988
xMONITOR Series
This is one of a family of MONITOR programs designed to work with
applications running in DESQview windows which are not DESQview
applications, but for which you want to perform some function related
to their presence in DESQview.
CMONITOR is a DESQview program to be used with DESQview and
communications programs such as RBBS and COM-AND where you want to
monitor the presence of a carrier signal in order to re-start the
program upon a loss of carrier.
xMONITORs use the DESQview API.
Usage: You must first install the CMONITOR programs in DESQview by
adding the CM-PIF.DVP file to the DESQview window menu by following
the standard procedures for adding programs. Be sure to use CM-PIF.DVP
since the window must run in background and the window size and memory
have been reduced to the minimum. After it is installed you can change
the command CM for opening the window to whatever you want and you
will need to change the Parameters line to agree with your location of
the communications program PIF file, xx-PIF.DVP, and the com port
to be monitored.
Syntax: CMONITOR pif_filespec com_port
^one and only one space
where pif_filespec is the d:\path\xx-PIF.DVP for the main application
being monitored and com_port is the communications port being used
by the application (use 1..4 for COM1..COM4).
CMONITOR works in conjuction with CMON. While in communciations
program execute CMON d:\path\CM-PIF.DVP from a DOS shell and
CMONITOR will be loaded and start monitoring the carrier. When you
want the monitoring to stop, execute CMON OFF. CMON will open and
close the window with CMONITOR. For the inter-process
communications that are needed for this to work both the comm PIF
and CMONITOR PIF must indicate that they share programs. You
indicate this by placing an asterisk in the 'Shared Program
Pathname' field.
CMONITOR checks for the presence of DESQview will not load unless
it is present. It is designed to work with DESQview version 2.01.
To terminate CMONITOR just close its window.
Upon restarting, a message with time and date is sent to standard
output which of course can be redirected to a printer.
|
;*************************************************************
; PROGRAM EQUATES, STRUCTURES AND MACROS
;*************************************************************
include dvapi.inc
cmd_tail equ 80h
cr equ 0dh
lf equ 0ah
eol equ '$'
time_date struc ;for restart message
msg db 'Restarted at '
hours db 'hh:'
mins db 'mm:'
secs db 'ss '
month db 'mm/'
day db 'dd/'
year db 'yy',cr,lf,eol
time_date ends
;*************************************************************
; CODE SEGMENT BEGINS
;*************************************************************
code_seg segment
assume cs:code_seg
org 100h ;org = 100h to make this into a
;".com" file
first: jmp load_monitor
;*************************************************************
; PROGRAM DATA
;*************************************************************
version equ 'Version 1.3'
db 'CMONITOR.COM'
db 'Copyright by John Poindexter'
db version
db '7DEC88'
align 2
PSP_seg dw ?
com_port_msr label word ;table of addresses of modem status registers
com1 dw 03feh
com2 dw 02feh
com3 dw 03eeh
com4 dw 02eeh
com_msr dw 0
;DESQview data
main label dword
main_win dw 2 dup (0)
top label dword
top_window dw 2 dup (0)
mon_mailbox db 'CMONITOR'
lmon_mailbox equ $-mon_mailbox
mail_waiting dd 0
move_fore_msg db 1bh,10h ;window manager stream id
dw lmove_fore_msg-4
db 0c1h ;make foreground
lmove_fore_msg equ $-move_fore_msg ;length of msg
pif_buffer db 416 dup (?)
install_message db cr,lf
db 'CMONITOR ',version,' installed.'
db cr,lf,eol
fail_message1 db cr,lf
db 'ERROR - No carrier detected on port specified.'
db cr,lf,eol
fail_message3 db cr,lf
db 'ERROR - DESQview is not present.'
db cr,lf,eol
file_error_msg db cr,lf
db 'ERROR - Unable to open PIF file for Communications '
db 'program.'
db cr,lf,eol
bad_handle_msg db cr,lf
db 'ERROR - Got a bad handle from main program.'
db cr,lf,eol
clock_msg time_date <>
;*************************************************************
; MONITOR PROCEDURE
; This keeps track of whether there is a carrier detected on
; the COM port being monitored.
;*************************************************************
monitor proc near
begin_monitor:
@send sizeof,mailme ;check for mail waiting
@pop mail_waiting
xor ax,ax
xor bx,bx
@cmp mail_waiting ;was there any
je check_carrier ;no, so continue checking
jmp finished ;yes, must be CLOSE msg
check_carrier: mov dx,com_msr ;check for carrier
in ax,dx
test ax,10000000b ;carrier detect is bit 7
jz lost_carrier
jmp recycle
lost_carrier: @call pause ;add some delay
@send free,main ;close the main window
;get window handle for window at 0,0 so can return
xor ax,ax ;start search from top of list
mov es,ax
xor bx,bx ;look at position 0,0
@call locate
mov ax,es
test ax,ax ;was a window found
jz re_load ;no, go ahead and reload
mov top_window[2],ax ;save handle of window found
mov top_window, 0 ;make sure low word is zero
;open new process for main application
re_load: push ds ;point to PIF buffer
pop es
lea di,pif_buffer
mov bx,416
@call newproc ;open main application in DV
mov main_win[2],bx ;get handle - high order word
mov main_win,0 ;make sure low order is zero
call clock ;send out restart message
lea dx,clock_msg
call prints
;return to what you were doing, by switching back to original top window
lea si,move_fore_msg ;setup to send message
xor dx,dx
mov cx,lmove_fore_msg
@push dssi
@push dxcx
@send write,top ;msg to move to foreground
jmp finished
recycle: @call pause ;give up rest of time slice
jmp begin_monitor ;go back for another check
finished: ret
monitor endp
;*************************************************************
; CNVRT1 PROCEDURE CONVERTS 16 BIT INTEGERS TO ASCII
;*************************************************************
; Call with: AX = integer
; Returns with: AX = ASCII
; Preserves all other registers
cnvrt1 proc near
aam ;make al into bcd
or ax,'00' ; and to ascii
xchg al,ah
ret
cnvrt1 endp
;*************************************************************
; CLOCK PROCEDURE GETS TIME OF DAY AND DATE
;*************************************************************
; Call with: a variable of time_date structure
; time_date struc
; hours db 'hh:'
; mins db 'mm '
; month db 'mm/'
; day db 'dd/'
; year db 'yy',cr,lf,eol
; time_date ends
clock proc near
push ax
push bx
push cx
push dx
mov ah,2ah ;get date
int 21h
sub cx,1900 ; last two digits
mov ax,cx ;make readable
call cnvrt1 ;convert to ascii
mov word ptr clock_msg.year,ax
xchg al,dh ;get month
call cnvrt1 ;convert to ascii
mov word ptr clock_msg.month,ax
xchg al,dl ;get day
call cnvrt1 ;convert to ascii
mov word ptr clock_msg.day,ax
mov ah,2ch ;get time
int 21h
xchg al,ch ;get hours
call cnvrt1 ;convert to ascii
mov word ptr clock_msg.hours,ax
xchg al,cl ;get minutes
call cnvrt1 ;convert to ascii
mov word ptr clock_msg.mins,ax
xchg al,dh ;get seconds
call cnvrt1 ;convert to ascii
mov word ptr clock_msg.secs,ax
pop dx
pop cx
pop bx
pop ax
ret
clock endp
;*************************************************************
; PRINTS PROCEDURE LIKE INT21H FUNCTION 9 BUT REDIRECTABLE
;*************************************************************
; Call with: DX = offset to string ending with $
; Preserves all other resgisters
prints proc near
push si
push bx
push cx
mov si,dx ; ptr to string text
sub cx,cx ; overall text length
ps1: lodsb
cmp al,eol ; ending $ ?
je ps9
inc cx
jmp short ps1
ps9:
mov bx,1 ; standard output device
mov ah,40h ; to write to
int 21h
pop cx ; recover registers
pop bx
pop si
ret
prints endp
;********************************************************************
; ARGV PROCEDURE to get command line arguments
;********************************************************************
; Call with: ES:BX = command line address
; (implicit: ES=PSP segment)
; AX = argument number (0 based)
;
; Returns: ES:BX = argument address
; AX = argument length
; (0=argument not found)
; Other registers preserved.
;
; If called with AX=0 (argv[0]) and running under
; MS-DOS version 3.0 or later, returns ES:BX pointing
; to program name in environment block and AX=length,
; otherwise returns ES:BX unchanged and AX=0.
;
cr equ 0dh ; ASCII carriage return
lf equ 0ah ; ASCII line feed
tab equ 09h ; ASCII tab
blank equ 20h ; ASCII space character
eqsign equ 3dh ; ASCII equal sign
argv proc near
or ax,ax ; is it argument 0?
jz argv8 ; yes, jump to get program name
xor ah,ah ; initialize argument counter
argv1: mov cx,-1 ; set flag = outside argument
argv2: inc bx ; point to next character
cmp byte ptr es:[bx],cr
je argv7 ; exit if carriage return
cmp byte ptr es:[bx],blank
je argv1 ; outside argument if ASCII blank
cmp byte ptr es:[bx],tab
je argv1 ; outside argument if ASCII tab
cmp byte ptr es:[bx],eqsign
je argv1 ; outside argument if ASCII equal sign
; if not blank, tab or equal sign...
jcxz argv2 ; jump if already inside argument
inc ah ; else count arguments found
cmp ah,al ; is this the one we're looking for?
je argv4 ; yes, go find its length
not cx ; no, set flag = inside argument
jmp argv2 ; and look at next character
argv4: ; found desired argument, now
; determine its length...
mov ax,bx ; save param. starting address
argv5: inc bx ; point to next character
cmp byte ptr es:[bx],cr
je argv6 ; found end if carriage return
cmp byte ptr es:[bx],blank
je argv6 ; found end if ASCII blank
cmp byte ptr es:[bx],tab
je argv6 ; found end if ASCII tab
cmp byte ptr es:[bx],eqsign
jne argv5 ; found end if ASCII equal sign
argv6: xchg bx,ax ; set ES:BX = argument address
sub ax,bx ; and AX = argument length
jmp argvx ; return to caller
argv7: xor ax,ax ; set AX = 0, argument not found
jmp argvx ; return to caller
argv8: ; special handling for argv=0
mov ax,3000h ; check if DOS 3.0 or later
int 21h ; (force AL=0 in case DOS 1)
cmp al,3
jb argv7 ; DOS 1 or 2, return null param.
mov es,es:[2ch] ; get environment segment from PSP
xor di,di ; find the program name by
xor al,al ; first skipping over all the
mov cx,-1 ; environment variables...
cld
argv9: repne scasb ; scan for double null (can't use
scasb ; (SCASW since might be odd addr.)
jne argv9 ; loop if it was a single null
add di,2 ; skip count word in environment
mov bx,di ; save program name address
mov cx,-1 ; now find its length...
repne scasb ; scan for another null byte
not cx ; convert CX to length
dec cx
mov ax,cx ; return length in AX
argvx: ; common exit point
ret ; return to caller
argv endp
;****************************************************************************
; INITIALIZATION PROCEDURE
;****************************************************************************
load_monitor proc near
assume cs:code_seg, ds:code_seg, es:nothing
mov PSP_seg,es ;save PSP
;make sure this is a DESQview environment
chk_dv: @call dvpresent
test ax,ax
jnz chk_level
lea dx,fail_message3
jmp test_failed
chk_level: mov bx,200h
@call apilevel ;requires version 2.00+
;DESQview actions
;setup to open main application if carrier is lost
install: mov bx,cmd_tail ;setup to get command line arg
mov es,PSP_seg
mov ax,1 ;get first argument
call argv
mov di,ax
mov byte ptr es:[di+bx],0 ;make filespec ASCIIZ
mov al,byte ptr es:[di+bx+1] ;get the second argument
sub al,31h ;convert to binary and adjust
push bx ;save it
mov bl,al
shl bl,1 ;double it for table lookup
xor bh,bh
mov ax,com_port_msr[bx]
mov com_msr,ax ;save address of com port msr
pop bx
push ds ;save DS
mov ax,es ;point to ASCIIZ filespec
mov ds,ax
mov dx,bx
mov ax,3d00h ;open file for reading
int 21h
pop ds
jnc read_file
lea dx,file_error_msg
jmp test_failed
read_file: mov bx,ax ;get file handle
lea dx,pif_buffer
mov cx,416 ;DV 2.00 PIFs are 416 bytes
mov ah,3fh ;read file
int 21h
mov ah,3eh ;close file
int 21h
;make sure starting off with carrier on com port specified
mov dx,com_msr
in ax,dx
test ax,10000000b
jnz success
lea dx,fail_message1
jmp test_failed
success: lea dx,install_message
mov ah,9
int 21h ;report installed
;get handle of main application
get_main: @call pause ;let CMON finish
@send read,mailme ;get message from main with handle
@pop dxcx ;clear out stack
@pop essi ;clear out stack
@send addr,mailme ;get address of main
@pop main
@mov esdi,main ;make sure we got a good handle
@call isobj
test bx,bx
jnz good_handle
lea dx,bad_handle_msg
jmp test_failed
;name this mailbox so CMON can find it
good_handle: lea si,mon_mailbox
xor dx,dx
mov cx,lmon_mailbox
@push dssi
@push dxcx
@send setname,mailme
;get window handle for window at 0,0 and make it foreground
xor ax,ax ;start search from top of list
mov es,ax
xor bx,bx ;look at position 0,0
@call locate
mov ax,es
test ax,ax ;was a window found
jz start_monitor ;no, go ahead and monitor
mov top_window[2],ax ;save handle of window found
lea si,move_fore_msg ;setup to send message
xor dx,dx
mov cx,lmove_fore_msg
@push dssi
@push dxcx
@send write,top ;msg to move to foreground
start_monitor: call monitor ;go wait for carrier loss
mov ax,4c00h ;normal exit
int 21h ;
test_failed: @call pause ;let CMON finish up
mov ah,9 ;if not get back to DOS after
int 21h ;printing error message
mov ax,4c01h ;and returning errorlevel
int 21h ;
load_monitor endp
code_seg ends
end first ;begin at first