fis-gtm/sr_unix/send_msg.c

114 lines
3.4 KiB
C

/****************************************************************
* *
* Copyright 2001, 2010 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include <stdarg.h>
#include "gtmmsg.h"
#include "error.h"
#include "fao_parm.h"
#include "util.h"
#include "util_out_print_vaparm.h"
#include "send_msg.h"
#include "caller_id.h"
#include "gtmsiginfo.h"
GBLREF bool caller_id_flag;
GBLREF va_list last_va_list_ptr;
GBLREF volatile int4 exit_state;
#ifdef DEBUG
static uint4 nesting_level = 0;
#endif
#define NOFLUSH 0
#define FLUSH 1
#define RESET 2
#define OPER 4
/*
** WARNING: For chained error messages, all messages MUST be followed by an fao count;
** ======= zero MUST be specified if there are no parameters.
*/
/* This routine is a variation on the unix version of rts_error, and has an identical interface */
void send_msg(int arg_count, ...)
{
va_list var;
int dummy, fao_actual, fao_count, i, msg_id;
char msg_buffer[1024];
mstr msg_string;
/* Since send_msg uses a global variable buffer, reentrant calls to send_msg will use the same buffer.
* Ensure we never overwrite an under-construction send_msg buffer with a nested send_msg call. The
* only exception to this is if the nested call to send_msg is done by exit handling code in which case
* the latest send_msg call prevails and it is ok since we will never return to the original send_msg()
* call again. Detect if ever this assmption gets violated with an assert.
*/
assert((0 == nesting_level) || (EXIT_IMMED == exit_state));
DEBUG_ONLY(nesting_level++;)
VAR_START(var, arg_count);
assert(arg_count > 0);
util_out_save();
util_out_print(NULL, RESET);
for (;;)
{
msg_id = (int) va_arg(var, VA_ARG_TYPE);
--arg_count;
msg_string.addr = msg_buffer;
msg_string.len = SIZEOF(msg_buffer);
gtm_getmsg(msg_id, &msg_string);
if (arg_count > 0)
{
fao_actual = (int) va_arg(var, VA_ARG_TYPE);
--arg_count;
fao_count = fao_actual;
if (fao_count > MAX_FAO_PARMS)
{
assert(FALSE);
fao_count = MAX_FAO_PARMS;
}
} else
fao_actual = fao_count = 0;
util_out_print_vaparm(msg_string.addr, NOFLUSH, var, fao_count);
va_end(var); /* need this before used as dest in copy */
VAR_COPY(var, last_va_list_ptr);
va_end(last_va_list_ptr);
arg_count -= fao_count;
if (0 >= arg_count)
{
if (caller_id_flag)
PRINT_CALLERID;
break;
}
util_out_print("!/", NOFLUSH);
}
va_end(var);
util_out_print(NULL, OPER);
util_out_restore();
/* it has been suggested that this would be a place to check a view_debugN
* and conditionally enter a "forever" loop on wcs_sleep for unix debugging
*/
DEBUG_ONLY(nesting_level--;)
}