This example shows the user application PROBE.C. The application uses the
subroutine approach to call the FFSTProbe function.
User Application using FFST and Trace Subroutines
/**************************************************************************/
/* probe.c: FFSTProbe sample */
/* */
/* This test program gives an example of using the FFSTProbe API and the */
/* TraceCreateEntry API by using 'wrapper' functions. The dummy API */
/* My_Dummy_Api returns a return code which is then used as the basis of */
/* firing a FFSTProbe via the wrapper function, callFFST. callFFST can */
/* be modified to include more or less data as needed. */
/* */
/**************************************************************************/
#define INCL_DOS
#define INCL_DOSMEMMGR
#define INCL_DOSPROCESS
#define INCL_FFST
#define NO_ERROR 0
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <FFST.h>
#include <trace.h>
/**************************************************************************/
/* Define probe ID for FFSTProbe called when dummy API fails. Probe ID */
/* is the unique identifier you use later to find the source of the */
/* failure. It should be unique within a DMI triplet (explained later) */
/* or within your product */
/**************************************************************************/
#define DUMMY_API_PROBE 22222
void callFFST ( ULONG input_version, /* FFST 'Wrapper' Function */
/* input version lets you change the wrapper */
/* without changing each call, just make sure */
/* the wrapper still treats the 'old' version */
/* the same and that any new code is */
/* conditioned on a new input_version # */
ULONG input_probe_flags, /* FFSTProbe probe flags */
ULONG input_severity, /* FFSTProbe severity */
ULONG input_probe_id, /* FFSTProbe ID */
CHAR* input_module_name, /* module name passed to probe */
ULONG input_log_data_length, /* log data length for the
system error log */
PVOID input_pError_log_data, /* pointer to the data for
system error log */
int argc);
/*****************************************************/
/* This is for a common trace entry routine */
/*****************************************************/
#define HKWD_TEST 220 /* major code */
#define hkwd_test_entry 0x0001 /* minor code for entry */
#define hkwd_test_exit 0x8001 /* minor code for exit */
struct
{
int count;
char textì12┘;
} trace_capture_start, trace_capture_end;
APIRET trace_out(ULONG major, ULONG minor, void *trace_data,
ULONG data_len); /* trace wrapper function */
/**************************************/
/* End of trace declarations for Main */
/**************************************/
ULONG My_Dummy_API(ULONG Mydata);
/**************************************************************************/
/* */
/* Main Application (this uses the callFFST wrapper function). */
/* */
/**************************************************************************/
int main ( int argc, char * argvì┘, char * envp )
{
ULONG rc = 0;
ULONG Mydata = 2;
ULONG userDataLen = 0;
PVOID pUserData = NULL;
printf ( "Starting FFSTProbe Sample\n" );
/**************************************/
/* Do the trace entry point */
/**************************************/
trace_capture_start.count = 3; /* just a number */
strncpy(trace_capture_start.text, "Start main", 12);
/******** CALL TraceCreateEntry function ****/
trace_out(HKWD_TEST,
hkwd_test_entry,
&trace_capture_start,
sizeof(trace_capture_start));
/***********************************************************************/
/* call the 'dummy' API so it returns a non-zero rc */
/***********************************************************************/
rc = My_Dummy_API ( Mydata );
if ( rc != NO_ERROR )
{
/********************************************************************/
/* The API has failed. Setup the userData to contain the failing rc */
/********************************************************************/
pUserData = calloc ( 2, sizeof ( ULONG ) );
memcpy ( pUserData, &rc, sizeof ( ULONG ) );
memcpy ( ( PBYTE ) pUserData + sizeof ( ULONG )
, &Mydata, sizeof ( ULONG ) );
/****************************************************************************/
/* Call the FFSTProbe wrapper function with a version of 1, */
/* Have FFST post the process status and environment variables in the */
/* syslog, a severity of 4, a probe id of DUMMY_API_PROBE which was */
/* previously defined as 22222, a module name of 'my_module_1', the length */
/* of logusrdta, the logUserData (equal to the failing rc (1) as */
/* setup above) and Argc is passed in to determine whether or not data */
/* should be retrieved from DMI. */
/****************************************************************************/
callFFST ( 1
, PSTAT_FLAG ║ PROC_ENV_FLAG
, SEVERITY4
, DUMMY_API_PROBE
, "my_module_1"
, 2 * sizeof ( ULONG )
, pUserData
, argc );
}
if (pUserData != NULL)
{
free(pUserData);
pUserData = NULL;
}
if (argc > 1)
{
printf("\nFFSTProbe sample ended not using DMI component:\n\n\n");
}
else
{
printf("\nFFSTProbe sample ended using DMI component:\n\n\n");
}
/**************************************/
/* Do the trace end point */
/**************************************/
trace_capture_end.count = 99;
strncpy(trace_capture_end.text, "End main", 12);
/******** CALL TraceCreateEntry function ****/
trace_out(HKWD_TEST,
hkwd_test_entry,
&trace_capture_end,
sizeof(trace_capture_end));
return 0;
}
/**************************************************************************/
/* callFFST is the FFSTProbe wrapper function. It allows you to code the */
/* FFSTProbe API once with data that is static as far as your usage is */
/* concerned and allows you to pass in dynamic data. It also helps */
/* insulate your code if you decide to change your 'static' options */
/**************************************************************************/
void callFFST ( ULONG input_version, /* FFST 'Wrapper' Function */
ULONG input_probe_flags, /* FFSTProbe probe flags */
ULONG input_severity, /* FFSTProbe severity */
ULONG input_probe_id, /* FFSTProbe ID */
CHAR* input_module_name, /* module name passed to probe */
ULONG input_log_data_length, /* log data length for the
system error log */
PVOID input_pError_log_data, /* pointer to the data for
system error log */
int argc)
{
APIRET rc = 0;
PVOID pvar_n0;
ULONG pvar_n1;
/***********************************************************************/
/* FFSTProbe API structures. Described in the API Guide */
/***********************************************************************/
FFSTPARMS FFSTParms;
PRODUCTINFO productInfo;
PRODUCTDATA productData;
DMIDATA DMIData;
DUMPUSERDATA dumpUserData;
MSGINSDATA msgInsData;
/***********************************************************************/
/* The PRODUCTDATA structure defines the DMI triplet which allows */
/* additional product information, including template repository */
/* filename, to be retrieved from DMI. DMI is a industry standard */
/* for desktop mgt */
/***********************************************************************/
productData.packet_size = sizeof ( productData );
productData.packet_revision_number = PRODUCTDATA_ASCII;
/* data can be ASCII or UNI */
productData.DMI_tag = "FFSTProbe Sample";
/* Customize for your program */
productData.DMI_vendor_tag = "IBM";
/*Customize for your company */
productData.DMI_revision = "1.00"; /* Customize */
/***********************************************************************/
/* The DMIDATA structure below is the information which can either be */
/* retrieved by DMI or passed in by the FFSTProbe function. The */
/* preferred method is to use DMI. In the example below, you can see */
/* the use of either depending on whether or not a parm was passed on */
/* call to this program */
/***********************************************************************/
if ( !(argc > 1) )
{
/********************************************************************/
/* Setting this structure to NULL indicates that the information is */
/* to be retrieved from DMI using the DMI triplet as defined in the */
/* productData structure. This is the preferred method. */
/* Other files in this example show how to build your own DMI */
/********************************************************************/
productInfo.pDMIData = NULL;
/********************************************************************/
/* Note: This shows the usage of message insert text and is NOT part*/
/* of the information that could or could not be retrieved from DMI */
/* This is included as an example of MsgInsTxt and how it can be */
/* used to send probe specific data to the SYSLOG (System Error Log)*/
/********************************************************************/
msgInsData.MsgInsTxtì0┘.insert_number = 1;
msgInsData.MsgInsTxtì0┘.insert_text = "We did use a DMI component";
}
else
{
/********************************************************************/
/* fill the DMI data structure - useful only in test environments */
/********************************************************************/
DMIData.packet_size = sizeof ( DMIData );
DMIData.packet_revision_number = DMIDATA_ASCII;
/* could be unicode instead */
DMIData.DMI_product_ID = "FFST_toolkt_sample";
/* note this is different than tag */
DMIData.DMI_modification_level = "000000";
DMIData.DMI_fix_level = "010101";
DMIData.template_filename = "PROBE.REP";
/* this file must be on the DPATH */
DMIData.template_filename_length = strlen (DMIData.template_filename)
* sizeof ( char );
/* since ascii is being used */
productInfo.pDMIData = &DMIData;
/********************************************************************/
/* Note: This shows the usage of message insert text and is NOT a */
/* of the information that could or could not be retrieved from DMI */
/********************************************************************/
msgInsData.MsgInsTxtì0┘.insert_number = 1;
msgInsData.MsgInsTxtì0┘.insert_text = "We did not use a DMI component";
}
/***********************************************************************/
/* set the pointers up for PRODUCTINFO */
/***********************************************************************/
productInfo.pProductData = &productData; /* This points to the DMI
related data */
/***********************************************************************/
/* set up some DUMPUSERDATA items */
/***********************************************************************/
pvar_n0 = "Dump user data"; /* Anything can be dumped
here up to 32 Kbytes */
pvar_n1 = 2;
dumpUserData.no_of_variables = 2;
dumpUserData.DumpDataVarì0┘.var_n_length = strlen(pvar_n0) + 1;
dumpUserData.DumpDataVarì0┘.var_n = pvar_n0;
dumpUserData.DumpDataVarì1┘.var_n_length = sizeof(ULONG);
dumpUserData.DumpDataVarì1┘.var_n = (PVOID)(&pvar_n1);
/***********************************************************************/
/* set up a couple of MSGINSDATA messages- just to show it can be done */
/***********************************************************************/
msgInsData.no_inserts = 2;
msgInsData.MsgInsTxtì1┘.insert_number = 2;
msgInsData.MsgInsTxtì1┘.insert_text = "Message insert variable 2";
/***********************************************************************/
/* set the FFSTPARMS structure, most values from DEFINEs above. */
/* See API GUIDE for details on each field and their possible values */
/***********************************************************************/
FFSTParms.packet_size = sizeof ( FFSTParms );
FFSTParms.packet_revision_number = FFSTPARMS_OS2_ASCII;
/* ASCII vs UNICODE data */
FFSTParms.module_name = input_module_name;
FFSTParms.probe_ID = input_probe_id;
FFSTParms.severity = input_severity;
FFSTParms.template_record_ID = input_probe_id;
FFSTParms.pMsgInsData = &msgInsData;
FFSTParms.probe_flags = input_probe_flags;
FFSTParms.pDumpUserData = &dumpUserData;
/* dump data is stored in .DMP files */
FFSTParms.log_user_data_length = input_log_data_length;
FFSTParms.log_user_data = input_pError_log_data;
/* log data is stored as part of the SYSLOG entry */
/***********************************************************************/
/* Call the FFSProbe API */
/***********************************************************************/
if ( input_version == 1)
{
rc = FFSTProbe ( &productInfo, &FFSTParms);
}
printf("\n----- Fired the FFSTProbe, rc=%d\n",rc);
/* for example only, do not do this in customer level code */
}
/**************************************************************************/
/* This is the dummy API for use in the example. It can easily set */
/* non-zero rc's */
/**************************************************************************/
ULONG My_Dummy_API ( ULONG Mydata )
{
if ( Mydata != 123456 )
{
return 1;
}
else
{
return 0;
}
}
/**************************************************************************/
/* Trace events function */
/**************************************************************************/
APIRET trace_out(ULONG major, ULONG minor, void *trace_data, ULONG data_len)
{
TCEREQUEST packet;
APIRET rc;
packet.packet_size = sizeof packet; /* Size of packet in bytes */
packet.packet_revision_number = TRACE_RELEASE; /* Revision level of trace */
packet.major_event_code = major; /* Major code event to be logged */
packet.minor_event_code = minor; /* Minor code event to be logged */
packet.event_data_length = data_len; /* Length of callers event buffer*/
packet.event_data = trace_data; /* Pointer to callers buffer */
/* call the TraceCreateEntry function */
rc = TraceCreateEntry(&packet);
return rc;
}