ENF listener code examples

A program can use one of the following methods to determine whether the z/OSMF server is up or down in the sysplex:
  • An APF-authorized program can use the ENFREQ LISTEN service to specify a listen exit for ENF event code 83 that tells the program the z/OSMF server is up and running. For an example of this technique, see the coded samples in Examples for an authorized program.
  • An unauthorized program cannot use the ENFREQ LISTEN service. However, it can periodically check the global storage pointer, which is mapped by macro IZUGSP. For an example of this technique, see the coded sample in Example for an unauthorized program.

Examples for an authorized program

Example program IZULSTEN shows how an APF-authorized program can listen for z/OSMF server status. IZULISTEN invokes the sample exit routine, IZULST00, which must reside in the link pack area (LPA). Both sample programs are written in assembler language.

Figure 1. Example of an authorized program that listens for z/OSMF server events (Part 1 of 2)

IZULSTEN  CSECT
IZULSTEN  AMODE 31
IZULSTEN  RMODE ANY

          STM   14,12,12(13)        Save caller's registers
          BALR  12,0                Establish module base

@ESTART   EQU   *
          SAM31                     Ensure 31 bit mode
          USING @ESTART,12          Establish addressability
          MODID                     Eyecatcher and date
          SR    15,15               Set return code to 0

* Set mode to Supervisor State
          WTO   'ENTERING PGM...'
          MODESET MODE=SUP
          MODESET EXTKEY=ZERO,SAVEKEY=(2),WORKREG=7
          LR    8,2                 Save user key

* Load ENF IZULST00 Listen Exit from LPA area
          LOAD  EP=IZULST00,LOADPT=IZULS00@

          SR    15,15               Set return code to 0
          L     2,IZULS00@
          L     4,A31MASK
          OR    2,4             Must be 31-bit addressing

          ST    13,SAVEA+4
          LA    13,SAVEA           Provide save area

          WTO   'Now registering as a listener for ENF code 83.'
* Issue LISTEN Request for z/OSMF event code (all functions)
          ENFREQ ACTION=LISTEN,   -- Function                          +
               CODE=ENFC83,       -- Event code                        +
               EXIT=(2),          -- Exit address                      +
               QUAL=ENF83CUP,     -- z/OSMF is up?                     +
               QMASK=ALL,         -- Set mask of all 4 bytes           +
               ESTBNME=THISMOD,   -- Establisher name                  +
               EXITNME=IZULST00,  -- Exit name                         +
               DTOKEN=IZULTOKN    -- Returned token field
          LTR   15,15
          JNZ   ERRGO
          B     @LEXIT

* Error exit, to print the return code
ERRGO     DS    0H
          ST    15,RETC
          WTO   'ENFREQ request error!'

          MVC   DataToConvert,RETC
          UNPK  ZonedArea,DataToUnpack
          TR    CharData,TRTBL
          MVC   ERRCODE,CharData

          MVC   WTOAREA,WTOLIST
          LA    5,ERRLEN
          STH   5,ERRMSGA
          MVC   ERRMSG,ERRMSGC

          LA    2,ERRMSGA                   Point to message in storage
          WTO   TEXT=(2),MF=(E,WTOAREA)     Write the message

@LEXIT    DS    0H
          LR    2,8                     Restore user key
          MODESET KEYADDR=(2),WORKREG=7
          MODESET MODE=PROB
          WTO   'End of zOSMF listener routine.'
Figure 2. Example of an authorized program that listens for z/OSMF server events (Part 2 of 2)

* Return control
          L     13,SAVEA+4
          L     14,12(13)                  RESTORE CALLERS REGS
          LM    0,12,20(13)                PRESERVE REG 15 - RC
          BR    14                         RETURN TO CALLER

          DS    0F
ENFC83    EQU   83
ENF83CUP  DC    X'80000000'          z/OSMF is up
A31MASK   DC    X'80000000'          High bit for 31-bit addressing

IZULTOKN   DS    F
ENFPTR    DS    A
SAVEA     DS    18F
RETC      DS    F
IZULST00  DC    CL8'IZULST00'
IZULS00@  DS    A
THISMOD   DC    CL8'IZULSTEN'

* Work area for conversion of addr to char string
DataToUnpack   DS    CL5
               ORG   DataToUnpack
DataToConvert  DS    CL4
DataToCvtXtra  DS    CL1
ZonedArea      DS    CL9
               ORG   ZonedArea
CharData       DS    CL8
ExtraChar      DS    CL1

* Table for converting
TRTBL           DC    XL256'00'
                ORG   TRTBL+240            Advance to offset F0 in table
                DC    C'0123456789ABCDEF'  Get ch 0 (F0x) at off F0
                DS    0F

WTOLIST   WTO   TEXT=,MF=L           List form
WTOLEN    EQU   *-WTOLIST            Length to move
WTOAREA   DS   CL(WTOLEN)   WTO in dyn area for modifiable msgs
ERRMSGC   DC   C'The return code of ENQREQ is: '
*
* Error message format
          DS  0F
ERRMSGA   DC  AL2(ERRLEN)
ERRMSG    DS  CL(L'ERRMSGC)
ERRCODE   DS  CL8
ERRLEN    EQU *-ERRMSG

*
* - External control blocks
          CVT   DSECT=YES
* ENF facility vector table create by system. Pointed to from CVT.
          IEFENFCT
* ENFREQ Macro area mapping
DATAAREA  DSECT
          IEFENFPM
LENODATA  EQU   *-DATAAREA
          END
Figure 3 shows IZULST00, which is an example of an ENF listener exit routine for the listener program that is shown in Figure 1 and Figure 2. To be used by an authorized program, the exit routine must reside in the link pack area (LPA).
Figure 3. Example of an ENF listener exit routine for ENF code 83

IZULST00  CSECT
IZULST00  AMODE 31
IZULST00  RMODE ANY

          STM   14,12,12(13)        Save caller's registers
          BALR  12,0                Establish module base

@ESTART   EQU   *
          SAM31                     Ensure 31 bit mode
          USING @ESTART,12          Establish addressability
          MODID                     Eyecatcher and date
          SR    15,15               Set return code to 0
          LR    2,1                 Save Register 1            
          WTO   'z/OSMF listen exit (IZULST00) receives control.' 
          L     3,0(2)              Address of IZUENF83 data area
          USING IZUENF83,3          Establish addressability

* For reentrancy, obtain storage for the local modifiable variables.
          USING WORKAREA,8          WORKAREA mapped at addr in Reg 8
          GETMAIN RU,LV=WORKAREL,LOC=31  Allocated save/work area
          LR    8,1                 Save the addr of obtained storage
* Clear WORKAREA
          MVI   WORKAREA,X'00'      Clear the first byte
          MVC   WORKAREA+1((L'WORKAREA)-1),WORKAREA
          ST    13,SAVEA+4
          LA    13,SAVEA           Provide save area
          
* Add your process logic here, for example ...
* Check if the event is for UP/DOWN
          L     7,IZUENF83_Status
          L     9,TESTBIT
          NR    7,9
          LTR   7,7
          BNZ   IZUON               When High bit is on
          WTO   'z/OSMF is down.'
          B     NEXTDO
IZUON     DS 0H
          WTO   'z/OSMF is up.'
    
NEXTDO    DS 0H
* Print host and uri information
          MVC   WTOMSG(PARTURIL),IZUENF83_URI
          MVC   WTOAREA,WTOLIST
          LA    9,WTOMSGL
          STH   9,WTOMSGA
          LA    5,WTOMSGA                   Point to msg in storage
          WTO   TEXT=(5),MF=(E,WTOAREA)     Write the message

* Return control
          L     13,SAVEA+4
          FREEMAIN RU,A=(8),LV=WORKAREL    Free save/workarea
          L     14,12(13)                  RESTORE CALLERS REGS
          LM    0,12,20(13)                PRESERVE REG 15 - RC
          BR    14                         RETURN TO CALLER

WTOLIST   WTO   TEXT=WTOMSG,MF=L     List Form
WTOLEN    EQU   *-WTOLIST            Length to move
TESTBIT   DC    X'80000000'

WORKAREA  DSECT
SAVEA     DS    18F
WTOAREA   DS   CL(WTOLEN)   WTO in dyn area for modifiable msgs

WTOMSGA   DC  AL2(WTOMSGL)
WTOMSG    DS  CL(PARTURIL)
WTOMSGL   EQU *-WTOMSG
PARTURIL  EQU 80
WORKAREL  EQU *-WORKAREA        WORKAREA DSECT length            
          IZUENF83 DSECT=YES
          END

Example for an unauthorized program

Figure 4 shows a sample program in REXX that can be used to query the z/OSMF global storage area, which is mapped by the macro IZUGSP.

Figure 4. Example of a REXX routine that allows an unauthorized program to listen for z/OSMF server events
/* rexx  */

/* Locate the system ECVT area */
CVT@ = C2d(Storage(10,4))
ECVT@   = C2d(Storage(D2x(CVT@ + 140),4))

/* Locate Address of z/OSMF Global Storage */
/* ECVTIZUGSP offset is 976                */
IZUGSP@   = C2d(Storage(D2x(ECVT@ + 976),4))
if IZUGSP@ = 0 then exit
 
/* Format the address to HEX string for visible */
IZUGSP$HEX  = C2x(Storage(D2x(ECVT@ + 976),4))

/* Print values from area mapped by IZUGSP */
IZUGSP_ID   = Storage(D2x(IZUGSP@),8)
IZUGSP_STATUS$HEX = C2x(Storage(D2x(IZUGSP@+8),4))
IZUGSP_URI = storage(D2x(IZUGSP@+12),274)

Say "Address of z/OSMF Global Storage is :"IZUGSP$HEX
Say "Eyecather field is :"IZUGSP_ID
 
/* High Bit is on when z/OSMF is active,
otherwise z/OSMF is inactive.            */
Say "Status and URI length field in HEX format is :"IZUGSP_STATUS$HEX
 
Say "URI field is :"IZUGSP_URI

exit