Scenario: Exit program for Watch for Event

The Watch for event function is started by the Start Watch (STRWCH) command or the Start Watch (QSCSWCH) API to notify the user by calling an exit program when the specified event occurs. An event can be a message that is sent to a message queue, a job log, a Licensed Internal Code log entry, or a Product Activity Log (PAL) entry, which shows errors that occurred in disk and tape units, during communications, or on workstations.

The user-written exit program is called in the circumstances specified in the Watch option setting parameter. Here is an example of a Watch for Event exit program, which is written in C.

Use this exit program as a starting point to help you create your own watch for event exit program. You can modify the code to allow the program to perform additional functions.

Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.
/*************************************************************************
** file = mywchpgm.c
**
** Example of an Exit Program for Watch for Event.
**
** This program will be called by the watch for event support when CPF0907
** message is sent to the history log (QHST message queue in library QSYS).
**
** The program will call a cleanup program to free system storage and,
** if the available storage is less than 5%, the program will perform some
** more actions (not defined).
**
**************************************************************************/
#include <decimal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <except.h>    /* _INTRPT_Hndlr_Parms_T is typedefed	         */
#include <escwcht.h>   /* Include for Watch Exit Program packaged in     */
                       /* QSYSINC/H Source Physical File                 */
 
/****************** Prototypes *******************************************/
void UNEXPECTED_HDLER (_INTRPT_Hndlr_Parms_T *errmsg);

/* Declare variables to receive parameters                           */
char   watch_option_setting[10],
       session_ID[10],
     * error_detected_ptr;

typedef struct {
                   Qsc_Watch_For_Msg_t msg_data;
                   char VarData[8776];         /* variable length data   */ 
} MsgFullData_t;

MsgFullData_t * MsgFullData;

int main (int argc, char *argv[])
{

   char * cAvailStorage[4];
   decimal(7,4) dAvailStorage;

   /* Variables to call a command                                       */
   int rc;
   char cmdtorun[128];
   #define CALL_MYCLNUP  "CALL PGM(MYLIB/MYCLNUP)"

   /*********************************************************************/
   /* Turn exception monitor on.				        */
   /*********************************************************************/
   #pragma exception_handler (UNEXPECTED_HDLER, 0, 0, _C2_MH_ESCAPE) 

   memcpy(watch_option_setting,argv[1],10);
   memcpy(session_ID,argv[2],10);
   error_detected_ptr = argv[3];
   MsgFullData = (MsgFullData_t *) argv[4];

   /* Verify if the exit program was called because a watched message   */
   /* occurred. This verification is useful if you have a watch         */
   /* session waiting for a message event and for a Licensed Internal Code log event        */
   if (memcmp(watch_option_setting,"*MSGID    ",10)==0) {

     /* Verify if the message ID that occurred is CPF0907               */
     /* This verification is useful if you are watching for more than   */
     /* one message in the same watch session                           */
     if (memcmp(MsgFullData->msg_data.Message_ID,"CPF0907",7)==0) {

        /* Call cleanup program to free space                       */
        strcpy(cmdtorun,CALL_MYCLNUP);
        rc = system(cmdtorun);   

	if (rc == 0) {
          /* Determine if the available storage space is less than 5%   */
          /* to do some extra processing                                */

          if (MsgFullData->msg_data.Length_Of_Replacement_Data > 0) {

            /* The remaining storage comes in the 4th field data in the */
            /* message replacement variable. See CPF0907 message        */
            /* description for a better understanding                   */
            memcpy(cAvailStorage,
                   (char *) (argv[4] +
                          MsgFullData->msg_data.Offset_Replacement_Data + 66),
                   4);

            dAvailStorage = *(decimal(7,4) *) cAvailStorage; 

            if (dAvailStorage <= 5.00) {
              /* Do some extra processing                               */
            }
          }
	}
	else { /* Error on clean-up program                             */
          UNEXPECTED_HDLER(NULL); /* Return error and exit              */
	}
     }
     else {
       /* Add code in case you are expecting any other message ID       */
     }
   }

   /* Verify if the exit program was called because a Licensed Internal Code log occurred  */
   else if (memcmp(watch_option_setting,"*LICLOG   ",10)==0) {
      /* Not needed for this watch session                              */
   }

   memcpy(error_detected_ptr,"          ",10); /* No error detected by
                            watch exit program, return blanks and
                            continue watching                           */
   #pragma disable_handler
   return (0);
}

/********************************************************************/
/*   FUNCTION NAME:  UNEXPECTED_HDLER	                            */
/*                                                                  */
/*   FUNCTION :      Handle unexpected exceptions that may occur    */
/*		     during the invocation of this pgm.		    */
/*                                                                  */
/********************************************************************/
void UNEXPECTED_HDLER (_INTRPT_Hndlr_Parms_T *errmsg)
{
   memcpy(error_detected_ptr,"*ERROR    ",10); /* An error occurred
                           on the watch exit program. Return *ERROR
                           and End the watch session                */   
   exit(EXIT_FAILURE);
}