; INFSND - Sends message to all Infinity users
; Modified from a distant version of an AMUS donated utility BRDCST
; by Dave Greene
;
; Edit History:
;
; 11/26/90      Created                                                 DJG
;
       SEARCH  SYS
       SEARCH  SYSSYM
       SEARCH  TRM

       VMAJOR=1
       VMINOR=0
       VEDIT=1.

;
;       Macro's
;
DEFINE  SEND    INCHR
       MOVB    INCHR,D1
       FILOTB  DDB(A4)
ENDM

DEFINE  TRMENT  TERM,CODES
       RAD50   /TERM/
       LWORD   CODES-.
ENDM

;
;       Workarea and Constants
;
       DSECT
       .=0
DDB:    BLKB    D.DDB
JOB:    BLKB    8.
PBUF:   BLKB    8.
SHOW:   BLKW    1
SILENT: BLKW    1
       MEMSIZ=.
       PSECT

BRDCST:
       PHDR    -2,-1,PH$REU!PH$REE

       GETIMP  MEMSIZ,A4

; Allow lower case input
       JOBIDX
       MOV     JOBTRM(A6),A6
       ORW     #T$ILC,@A6

; Check what user wants to send
       BYP
       LIN                             ; anything to send?
       BNE     0$
       TYPE    <Message: >
       KBD     EXIT
       BYP
       LIN
       JEQ     EXIT                    ; leave if not...

; Setup output device info
0$:
       MOVW    #[TRM],DDB+D.DEV(A4)    ; move in device name,
       INIT    DDB(A4)                 ; and initialize.

; Clear flags
       CLRW    SHOW(A4)                ; show senders name
       CLRW    SILENT(A4)              ; output bell
       JOBIDX  A0                      ; A0 -> out JCB...

; This is the start of the program.   Check for valid switches.
1$:
       CMPB    @A2,#'/                 ; switch marker?
       BNE     10$                     ;  no - done checking for switches
       MOVB    1(A2),D1                ;  yes - D1 = switch character
       UCS                             ; fold
       CMPB    D1,#'T                  ; suppress sending senders jobname?
       BNE     5$                      ;  no - check other switches
       SETW    SHOW(A4)                ;  yes - flag it
       ADD     #2,A2                   ; bump past this switch
       BYP                             ; skip spaces
       BR      1$                      ; continue check
5$:
       CMPB    D1,#'S                  ; silent mode?
       BNE     10$                     ;  no - done with switches
       SETW    SILENT(A4)              ;  yes - flag it
       ADD     #2,A2                   ; bump past this switch
       BYP                             ; and spaces
       BR      1$                      ; and continue check

; save sending jobs jobname to display with message
10$:
       TSTW    SHOW(A4)                ; are we sending this info
       BNE     BEGIN                   ;  no - skip this
       PUSH    A2                      ; save A2...
       LEA     A1,JOBNAM(A0)           ; A1 -> job name field...
       LEA     A2,JOB(A4)              ; A2 -> job name work area...
       UNPACK                          ; unpack name into work area...
       UNPACK
       MOVB    #32.,@A2
       POP     A2

;***********
;*  BEGIN  *
;***********
; This is the main loop.  Scan through all entries in the job table, and
; check for jobs that look like they are running Infinity.  Rule out
; task manager jobs and the like.
BEGIN:
       MOV     JOBTBL,A0               ; -> first JCB pointer...
LOOP:
       MOV     (A0)+,D7                ; -> JCB...
       BEQ     LOOP                    ; if not allocated...
       CMP     D7,#-1                  ; test for end of table...
       JEQ     EXIT                    ; leave if so...
       MOV     D7,A1                   ; A1 -> current job entry

; Test to see if this job is me
       JOBIDX  A6                      ; get my job
       CMP     A6,A1                   ; same?
       BEQ     LOOP                    ; yes - skip me

; Test to see if this job is running an Infinity Module
       CMMW    JOBPRG(A1),#[INF]       ; program starts with "INF"
       BNE     LOOP                    ; no - forget

; Test for task managr job just in case it's not using PSEUDO tdv
       CMM     JOBNAM(A1),#[TAS]_16.+[K  ]     ; is job a TASK MANAGR?
       BEQ     LOOP                    ;   branch if so

; Test for job spawned by MULTI.  Send to base job
       MOV     JOBATT(A1),D7           ; get attached job
       BEQ     10$                     ; if none then proceed
       MOV     D7,A1                   ; now use base job

; Ignore spooler jobs and slaves to TASK MANAGR
10$:
       MOVW    JOBTYP(A1),D7           ; get job type
       ANDW    #<J.LPT!J.TSK>,D7       ; mask off spooler and task bits
       JNE     LOOP                    ; loop if either set

; Now check to see if the terminal qualifies for the message
MSGSND:
       MOV     JOBTRM(A1),D7           ; D7 -> TCB...
       JEQ     LOOP                    ; br if no terminal...
       MOV     D7,A5                   ; A5 -> TCB...
       MOV     2(A5),A3                ; A3 -> interface driver...
       SUB     #4,A3                   ; A3 -> I.D. name...
       CMM     @A3,PSEUDO              ; PSEUDO?
       JEQ     LOOP                    ; skip if so...

; Terminal OK.  Prepare to output message
       MOV     -4(A5),D.FIL(A4)        ; move in terminal name...
       OPENO   DDB(A4)                 ; open for output

; Prepare to output bell
       TSTW    SILENT(A4)              ; suppressing bell?
       BNE     FNDTRM                  ;  yes - forget it
       SEND    #7                      ; ring the chime

;************
;*  FNDTRM  *
;************
;
; This section of code, uses a table which contains information on
; how to activate the unshifted status line in REVERSE mode.  If a terminal
; does not have info in this table, this program will output it much the
; same way as send does.
;
; Table consists of entries of names of terminal drivers, and then the
; offset to the routine that contains the appropriate escape codes.
;
FNDTRM:
       PUSH    A1                      ; save work register
       LEA     A3,VALIDT               ; A3 -> table
       MOV     16(A5),A1               ; A1 -> terminal driver
20$:
       TST     @A3                     ; end of table?
       BEQ     90$                     ;  yes - didn't find it
       CMM     (A3)+,-4(A1)            ; found a match?
       BEQ     30$                     ;  yes - cool
       ADD     #4,A3                   ;  no - goto next entry in table
       BR      20$                     ;
30$:
       ADD     @A3,A3                  ; add offset to current location

; A3 -> status line activation string null terminated
40$:
       TSTB    @A3                     ; are we at end?
       BEQ     90$                     ;  yes - good
       SEND    (A3)+                   ;  no - send next character in string
       BR      40$                     ; and continue
90$:
       POP     A1                      ; restore A1

; Now we are almost ready to send message.  First, we need to check to
; see if we will be sending the Senders jobname.
       TSTW    SHOW(A4)                ; sending jobname?
       BNE     START                   ;  no - forget it
       CLR     D2                      ; D2 keeps track of characters sent
       LEA     A1,JOB(A4)              ; A1 -> job name work area...
       SEND    #'(                     ; parens are nicer
       INC     D2
NLOOP:
       MOVB    (A1)+,D1                ; get next character of jobname
       CMPB    D1,#'                   ; a space?
       BNE     SENDIT                  ;  yes - done with this
       BR      ENDPAR                  ;
SENDIT:
       FILOTB  DDB(A4)                 ; send character
       INC     D2                      ; and incrment "sent" count
       BR      NLOOP                   ; and continue
ENDPAR:
       SEND    #')                     ; done - close parens
       INC     D2                      ;
START:
       MOVB    #32.,D1                 ; need a space seperator
       FILOTB  DDB(A4)                 ; output
       PUSH    A2                      ; save -> text line...

;***********
;*  OLOOP  *
;***********
; Main loop to output message.  We either send characters until end of line
; is reached, or 77 characters have been sent; which ever comes first.
;
OLOOP:
       MOVB    (A2)+,D1                ; get next byte of text and
       FILOTB  DDB(A4)                 ; output...
       INC     D2                      ; increment count
       CMP     D2,#77.                 ; 77 yet?
       BHIS    ESEND                   ;  yes - done
       LIN                             ; end of input line?
       BNE     OLOOP                   ; br if not, else
       POP     A2                      ; restore A2 and
       NEG     D2                      ; D2 will equal number of spaces
       ADD     #78.-1.,D2              ;   .. to fill out line
       TST     D2                      ;  (in case there is already stuff
       BMI     ESEND                   ;    on the status line)
       BEQ     ESEND
10$:                                    ; output filler spaces
       SEND    #32.                    ;
       SOB     D2,10$

; Done sending message.
ESEND:
       SEND    #127.                   ; terminate status line activity
       CLOSE   DDB(A4)                 ; close output file.
; Show this user, so we can tell who was/is effected.
       MOV     -4(A0),A1               ; Get last job entry
       MOVW    #-1_8.+11.,D1           ; dim
       TCRT
       TYPE    <User >                 ; display user name of person
       MOVW    #-1_8.+12.,D1           ; logged in at this job
       TCRT
       TTYL    JOBUSN(A1)
       CLR     D1
       MOVW    #-1_8.+11.,D1
       TCRT
       TYPE    < notified (>           ; and then the job they are logged
       MOVW    #-1_8.+12.,D1           ; in at
       TCRT
       PUSH    A2                      ; save A2...
       LEA     A1,JOBNAM(A1)           ; A1 -> job name field...
       LEA     A2,PBUF(A4)              ; A2 -> job name work area...
       UNPACK                          ; unpack name into work area...
       UNPACK
       CLRB    @A2
       POP     A2
       TTYL    PBUF(A4)
       MOVW    #-1_8.+11.,D1
       TCRT
       TYPECR  <)>
       MOVW    #-1_8.+12.,D1
       TCRT
       JMP     LOOP                    ; do next job
EXIT:
       CRLF                            ; done
       EXIT

PSEUDO:
       RAD50   /PSEUDO/
VALIDT:
       TRMENT  AM62,AM62
       TRMENT  AM60,AM62
       TRMENT  AM62A,AM62
       TRMENT  FLP62A,AM62
       TRMENT  <W50  >,WYSE50
       TRMENT  WY50,WYSE50
       TRMENT  WYSE50,WYSE50
       TRMENT  WY50I,WYSE50
       TRMENT  FLPW50,WYSE50

AM62:
       BYTE    27.,'z,32.,7.,0
       EVEN
WYSE50:
       BYTE    27.,'A,'1,'6,27.,'z,'(,
       EVEN
       END