;***************************************************************************
;*      NETSPY.M68  (Watch Dog)
;*
;*      Monitor system JOBs for lack of input...log them off after
;*      a three minute grace period if no CPU time used.
;*
;*      by Dave Heyliger - AMUS
;*
;############################################################################
;# How it works:
;# Basically, this program will check a list of JOBs (even all JOBs) by
;# examining the listing of YOUR JOBS that you should enter at the label
;# "JOBS" (at the end of this file). The program sleeps at three minute
;# intervals, waking up only to scan the JOBs listed. Once awake, it then
;# makes sure that these JOBs are not running an "exempt" program... i.e.,
;# if they are in an exempt program, they could sit on your system for
;# hours and never get logged off. If they are NOT running an exempt program,
;# and the CPU time has NOT changed for this JOB in the last 3 minutes, BYE!
;# List your exempt programs at label "EXEMPT" - include the /$$$$$$/ !
;#
;# Set up a mini JOB on your system that only runs NETSPY. It uses minimal
;# CPU time: after about 64 hours of operation, only 3 seconds CPU time used.
;# This JOB doesn't physically need a terminal, and needs only minimal memory.
;#
;############################################################################
;*
;*      Comments throughout program listing will inform you of any
;*      "customizing" you might need to perform before assembling.
;*
;***************************************************************************

       OBJNAM  NETSPY.LIT              ;the final product

       SEARCH SYS                      ;get the monitor calls...
       SEARCH SYSSYM
       SEARCH TRM

       VMAJOR=1                        ;define a version number
       VMINOR=0
       VEDIT=100.
       VEDIT=101.                      ;made no JOBPRG name show on "watch"
       VEDIT=102.                      ;deleted "tiw" routine.. not needed.
       VEDIT=103.                      ;get rid of spaces on non 6 char jobs
                                       ;before ZAP/N!
       VEDTI=104.                      ;get all non-actives on same pass

       PHDR    -1,0,PH$REU             ;program header
TOP:    JOBIDX  A6
       LEA     A5,BLANKS
       LEA     A4,JOBPRG(A6)
       MOV     @A5,@A4
TOP2:   SLEEP   #1800000.               ;sleep for 3 minutes (#600000.=1 min.)
       CTRLC   STOP                    ;quit on controlC
       MOV     JOBTBL,A0               ;JOB TABLE address to A0 [104]
       LEA     A1,JOBS                 ;JOBS (list to check) address to A1
       MOV     #0,D0                   ;D0 will be a counter for offset use

;--- Scan for the JOBs to be checked
;
SCAN:   MOV     (A0)+,A3                ;A3 now points to each JCB per SCAN
       MOV     A3,D1                   ;Set the status register
       JMI     TOP2                    ;if at end of JOBTBL, start over
       BEQ     SCAN                    ;if a "0" then look at next JCB
       LEA     A4,JOBNAM(A3)           ;valid JOB so get the NAME of the JOB
       CMM     @A1,@A4                 ;see if this name matches name in list
       BEQ     FOUND                   ;found a match!
       JMP     SCAN                    ;else try the next JOB on the system

;---    Found a JOB that is to be checked, so begin anaylsis
;       First, check to see that JOB is not running exempt prg.
;
FOUND:  LEA     A4,JOBPRG(A3)           ;match, so now get the program running
       LEA     A2,EXEMPT               ;list of programs that are exempt
       LEA     A6,MARKER               ;A6 points to special marker (end)
NXTPRG: CMM     @A2,@A6                 ;see if it is at the end of the list
       BEQ     TIME                    ;JOB not in exempt program if branch
       CMM     (A2)+,@A4               ;running an exempt program???
       BNE     NXTPRG                  ;at least not this program, but next?
       ADD     #4,A1                   ;exempt, so get next JOB 2 b checked
       ADD     #4,D0                   ;increment count offset value
       JMP     SCAN                    ;and check next guy

;---    Time to check to see if CPU time is same as 3 minutes ago.
;
TIME:   LEA     A4,JOBCPU(A3)           ;"tiw"... but for how long???
       LEA     A2,CPUBUF               ;point A2 to start of buffer
       ADD     D0,A2                   ;offset adjustment
       CMM     @A2,@A4                 ;time same as 3 minutes ago???
       BEQ     ZAPJOB                  ;yup, say goodbye
       MOV     (A4),@A2                ;else store the "new" CPU time
       ADD     #4,D0                   ;and adjust offset value
       ADD     #4,A1                   ;point A1 to next JOB on list
       JMP     SCAN                    ;and begin scanning system again


;---    This portion of the program will 1) ZAP PHONE#/N (or whatever)
;                                        2) FORCE PHONE# QUIT (or whatever)
;
; You might just want to ABORT the JOB (I don't know how you system works!).
; If you simply ABORT the JOB, you won't need the code for "FORCE...."
; that starts at the label BYETST:
;
ZAPJOB: PUSH    A0                      ;save JOBTBL pointer [104]
       PUSH    A1                      ;save JOBS pointer [104]
       PUSH    D0                      ;save offset pointer

       LEA     A4,ZAP                  ;A4 points to the ascii word "ZAP"
       LEA     A2,BYECMD               ;used for ascii ZAP/FORCE lines
SPACE1: CMPB    @A4,#40                 ;does A4 point to a space??
       BEQ     WHO                     ;if so, place what JOB to ZAP
       MOVB    (A4)+,(A2)+             ;else plop in the ZAP ascii data
       JMP     SPACE1                  ;and get the next character
WHO:    MOVB    @A4,(A2)+               ;move in the ascii " "
       PUSH    A3                      ;save this pointer
       LEA     A1,JOBNAM(A3)           ;point A1 to the JOB NAME
       UNPACK                          ;blast this into the CMD line
       UNPACK
LOKSPC: CMPB    -(A2),#40               ;get rid of extra spcs on non 6
       BEQ     LOKSPC                  ;  character JOBs
       INC     A2                      ;adjust
; take out next two lines if you are using ABORT
       MOVB    #57,(A2)+               ;and blast in a "/"
       MOVB    #116,(A2)+              ;and an "n"
       MOVB    #15,(A2)+               ;and a [cr]
       MOVB    #12,(A2)+               ;and a LF
       LEA     A2,BYECMD               ;repoint A2 to "ZAP PHONE#/N"
       AMOS                            ;"ZAP PHONE#/N" (or ABORT PHONE# or..)
       SLEEP   #1000.                  ;safety measure

; if you are NOT going to FORCE the JOB a CMD file, omit all below up to
; JMP SCAN - be sure to leave that line in.
;
BYETST: LEA     A4,FORCE                ;A4 points to the ascii word "FORCE "
       LEA     A2,BYECMD               ;A2 points to a command line buffer
SPACE2: CMPB    @A4,#40                 ;does A4 point to a space?
       BEQ     GETJOB                  ;if so, time to add JOB NAME to CMD
       MOVB    (A4)+,(A2)+             ;else plop in the FORCE ascii data
       JMP     SPACE2                  ;and get the next character
GETJOB: MOVB    @A4,(A2)+               ;move in the ascii " "
       POP     A3                      ;retrieve pointer
       LEA     A1,JOBNAM(A3)           ;point A1 to the JOB NAME
       UNPACK                          ;blast this into the CMD line
       UNPACK
       MOVB    #40,(A2)+               ;and blast in a " "
       LEA     A4,QUIT                 ;A4 points to ascii "QUIT "
LF:     CMPB    @A4,#12                 ;is it a line feed??
       BEQ     BYEBYE                  ;if so, FORCE {JOB} QUIT
       MOVB    (A4)+,(A2)+             ;else continue moving in ascii data
       JMP     LF                      ;and get the next character
BYEBYE: MOVB    @A4,@A2                 ;plop in the line feed
       LEA     A2,BYECMD               ;repoint A2 to start of CMD line
       AMOS                            ;FORCE {JOB} QUIT
;[104]
       JOBIDX  A6                      ;clear out STAT garbage
       LEA     A5,BLANKS
       LEA     A4,JOBPRG(A6)
       MOV     @A5,@A4
;[104]
       POP     D0                      ;get offsets [104]
       POP     A1                      ;get JOBS pointer
       POP     A0                      ;get JOBTBL pointer
       JMP     SCAN                    ;and get next offender



;----   ASCII data to follow  (up to label STOP)
;
ZAP:    ASCII   /ZAP /                  ;ascii "ZAP "; you might use /ABORT /
       EVEN                            ;just be sure to include the " " no
                                       ;matter what "ZAP" prg you have.

FORCE:  ASCII   /FORCE /                ;ascii "FORCE " (note " " again)
       EVEN

; NO space after .CMD file name (if you use it at all)
;
QUIT:   ASCII   /QUIT/                  ;ascii "QUIT" ; a cmd file (optional)
       BYTE    15                      ;[cr]
       BYTE    12                      ;LF
       EVEN

JOBS:   RAD50   /PHONE1/                ;list of JOBs to monitor on system
       RAD50   /PHONE2/                ;list them IN ORDER (like how you
       RAD50   /PHONE3/                ; would see them using STAT).
       RAD50   /PHONE4/
;       RAD50   /JOB1  /                ;possible other JOBs (6 chars always)
;       RAD50   /JOB2  /

; Below is the "exempt" programs: if a JOB is in one of these, get next JOB
;
EXEMPT: RAD50   /WELCOM/                ;ascii "WELCOM" : must have AT LEAST 1
;       RAD50   /LOG   /                ;possible other exempt prgs
;       RAD50   /DIR   /
;       RAD50   /....../                ;for "bogus 'AT LEAST 1' program
MARKER: RAD50   /$$$$$$/                ;end marker for exempt programs

; Be sure to provide 1 BLKL per JOB in JOBS listing (here it was PHONE1-4)
;
CPUBUF: BLKL    4                       ;buffer to store CPU time

; If your CMD line is smaller or larger, adjust this next value accordingly
; "FORCE PHONE# QUIT" is 19 bytes long (17 + [cr] + LF).
;
BYECMD: BLKB    26                      ;buffer to store CMD line plus some

BLANKS: RAD50   /      /
       EVEN

STOP:   EXIT
       END