fis-gtm/sr_unix/trans_log_name.c

129 lines
4.6 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 "gtm_ctype.h"
#include "gtm_string.h"
#include "gtm_stdlib.h"
#include "io.h"
#include "iosp.h"
#include "trans_log_name.h"
#include "send_msg.h"
/* Allocate a buffer to be used for passing a null-terminated environment-variable to GETENV.
* If more space is needed, we will expand later. Need to statically allocate space to hold "$gtmdbglvl"
* since this is the first environment variable that will be passed to trans_log_name and needs
* to be translated BEFORE doing any mallocs hence the initial static allocation of MAX_TRANS_NAME_LEN bytes.
*/
STATICDEF char trans_log_name_startbuff[MAX_TRANS_NAME_LEN];
STATICDEF int trans_log_name_buflen = MAX_TRANS_NAME_LEN - 1; /* length of buffer currently allocated */
STATICDEF char *trans_log_name_buff = &trans_log_name_startbuff[0];
int4 trans_log_name(mstr *log, mstr *trans, char *buffer, int4 buffer_len, translog_act do_sendmsg)
{
char *s_start, *s_ptr, *s_top, *tran_buff, *b_ptr, *b_top, ch;
int len, s_len;
int4 ret;
error_def(ERR_LOGTOOLONG);
ret = SS_NOLOGNAM; /* assume we don't find it */
b_ptr = buffer; /* b_ptr is points to next place to fill in in output buffer */
b_top = buffer + buffer_len;
s_start = log->addr;
s_top = s_start + log->len;
for (s_ptr = s_start; s_ptr < s_top; )
{
assert(s_ptr != buffer); /* should be no intersections between input and output buffer at any point of processing */
if ('$' == *s_ptr)
{ /* We hit a env var that needs to be translated - they start with $ */
/* For non-initial pass copy any non-env var text that we have passed over into output buffer
* and update output buffer pointer. Before that check if output buffer can hold that data.
*/
s_len = (int)(s_ptr - s_start);
if ((b_ptr + s_len) >= b_top)
{
ret = SS_LOG2LONG;
break;
}
memcpy(b_ptr, s_start, s_len);
b_ptr += s_len;
assert(b_ptr < b_top);
/* Move forward in input buffer (over text just processed) */
s_start = s_ptr++;
/* Get the env var name. Take care not to exceed input string length */
for ( ; (s_ptr < s_top) && (ch = *s_ptr, ('_' == ch) || ISALNUM_ASCII(ch)); s_ptr++)
;
s_len = (int)(s_ptr - s_start) - 1;
/* Copy it into "temporary-buffer" so we can null-terminate it and pass to GETENV */
if (trans_log_name_buflen <= s_len)
{ /* Currently allocated buffer is not enough. Expand it. */
assert(NULL != trans_log_name_buff);
if (trans_log_name_buff != trans_log_name_startbuff) /* do not free static starting buffer */
free(trans_log_name_buff);
trans_log_name_buff = malloc(s_len + 1);
trans_log_name_buflen = s_len + 1;
}
memcpy(trans_log_name_buff, s_start + 1, s_len);
trans_log_name_buff[s_len] = 0;
/* try to convert it */
if (NULL != (tran_buff = GETENV(trans_log_name_buff)))
{
s_start = tran_buff;
s_len = STRLEN(tran_buff);
ret = SS_NORMAL;
} else
{ /* if there is no env var then just copy the name of the env var name including $ */
s_len = (int)(s_ptr - s_start);
}
if ((b_ptr + s_len) >= b_top)
{
ret = SS_LOG2LONG;
break;
}
memcpy(b_ptr, s_start, s_len);
b_ptr += s_len;
assert(b_ptr < b_top);
/* move over env var just processed */
s_start = s_ptr;
} else
s_ptr++; /* keep going until you either hit end of string or $ */
}
if (SS_LOG2LONG != ret)
{ /* if there is anything left after the last env var name, copy it */
s_len = (int)(s_ptr - s_start);
if ((b_ptr + s_len) >= b_top)
ret = SS_LOG2LONG;
else
{
memcpy(b_ptr, s_start, s_len);
b_ptr += s_len;
assert(b_ptr < b_top);
}
}
assert(b_ptr < b_top); /* "<" instead of "<=" so it is safe to write the termination '\0' character */
/* create the return mstr */
trans->addr = buffer;
trans->len = INTCAST(b_ptr - buffer);
assert(trans->len < buffer_len);
/* Null-terminate returned string (even though an mstr), as this is relied upon
* by callers who do ATOI etc. directly on the return string.
*/
trans->addr[trans->len] = '\0';
if (do_sendmsg && (SS_LOG2LONG == ret))
send_msg(VARLSTCNT(5) ERR_LOGTOOLONG, 3, log->len, log->addr, buffer_len - 1); /* - 1 for terminating null byte */
return ret;
}