/*
** OSSP l2 - Flexible Logging
** Copyright (c) 2001-2005 Cable & Wireless
** Copyright (c) 2001-2005 The OSSP Project
** Copyright (c) 2001-2005 Ralf S. Engelschall
**
** This file is part of OSSP l2, a flexible logging library which
** can be found at http://www.ossp.org/pkg/lib/l2/.
**
** Permission to use, copy, modify, and distribute this software for
** any purpose with or without fee is hereby granted, provided that
** the above copyright notice and this permission notice appear in all
** copies.
**
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
** l2_format.c: extra formatters
*/
#include
#include "l2.h"
#include
l2_result_t
l2_util_fmt_string(
l2_context_t *ctx, const char id, const char *param,
char *bufptr, size_t bufsize, size_t *buflen, va_list *ap)
{
char *cpStr;
size_t nStr;
cpStr = va_arg(*ap, char *);
nStr = (size_t)va_arg(*ap, int);
if (cpStr == NULL)
return L2_ERR_ARG;
if (nStr > bufsize)
return L2_ERR_MEM;
memcpy(bufptr, cpStr, nStr);
*buflen = nStr;
return L2_OK;
}
l2_result_t
l2_util_fmt_dump(
l2_context_t *ctx, const char id, const char *param,
char *bufptr, size_t bufsize, size_t *buflen, va_list *ap)
{
static const char hex_table[] = "0123456789abcdef";
static const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
unsigned char base64_in[3];
unsigned char base64_out[4];
size_t nData;
unsigned char *ucpData;
unsigned char uc;
unsigned char *cpO;
unsigned char *cpI;
int i;
int n;
/* fetch data pointer and data size from argument list */
ucpData = va_arg(*ap, unsigned char *);
nData = (size_t)va_arg(*ap, int);
/* argument sanity check */
if (ucpData == NULL)
return L2_ERR_ARG;
/*
* textual dumping: "foo\1bar" -> "foo\x01bar"
*/
if (strcmp(param, "text") == 0 || param[0] == '\0') {
cpI = ucpData;
cpO = (unsigned char *)bufptr;
while (cpI < (ucpData+nData)) {
uc = *cpI++;
if (isprint((int)uc)) {
if ((char *)cpO >= (bufptr+bufsize))
return L2_ERR_MEM;
*cpO++ = uc;
}
else if (uc == '\\') {
if ((char *)(cpO+1) >= (bufptr+bufsize))
return L2_ERR_MEM;
*cpO++ = '\\';
*cpO++ = '\\';
}
else if (uc == '\t' || uc == '\r' || uc == '\n') {
if ((char *)(cpO+1) >= (bufptr+bufsize))
return L2_ERR_MEM;
*cpO++ = '\\';
switch ((int)uc) {
case '\t': *cpO++ = 't'; break;
case '\r': *cpO++ = 'r'; break;
case '\n': *cpO++ = 'n'; break;
default: break;
}
}
else {
if ((char *)(cpO+3) >= (bufptr+bufsize))
return L2_ERR_MEM;
*cpO++ = '\\';
*cpO++ = 'x';
*cpO++ = hex_table[(uc >> 4) & 0xf];
*cpO++ = hex_table[uc & 0xf];
}
}
*buflen = ((char *)cpO - bufptr);
}
/*
* hexadecimal dumping: "foo\1bar" -> "66:6f:6f:01:62:61:72"
*/
else if (strcmp(param, "hex") == 0) {
if (((nData * 3) - 1) > bufsize)
return L2_ERR_MEM;
cpO = (unsigned char *)bufptr;
for (i = 0; i < nData; i++) {
uc = *ucpData++;
*cpO++ = hex_table[(uc >> 4) & 0xf];
*cpO++ = hex_table[uc & 0xf];
if (i < (nData - 1))
*cpO++ = ':';
}
*buflen = (nData * 3) - 1;
}
/*
* Base64 dumping: "foo\1bar" -> "Zm9vAWJhcg=="
*/
else if (strcmp(param, "base64") == 0) {
/* bulk encoding */
n = 0;
while (nData >= 3) {
base64_in[0] = *ucpData++;
base64_in[1] = *ucpData++;
base64_in[2] = *ucpData++;
nData -= 3;
base64_out[0] = ( base64_in[0] >> 2);
base64_out[1] = ((base64_in[0] & 0x03) << 4) + (base64_in[1] >> 4);
base64_out[2] = ((base64_in[1] & 0x0f) << 2) + (base64_in[2] >> 6);
base64_out[3] = ( base64_in[2] & 0x3f);
if (n + 4 > bufsize)
return L2_ERR_MEM;
bufptr[n++] = base64_table[base64_out[0]];
bufptr[n++] = base64_table[base64_out[1]];
bufptr[n++] = base64_table[base64_out[2]];
bufptr[n++] = base64_table[base64_out[3]];
}
/* now worry about padding with remaining 1 or 2 bytes */
if (nData != 0) {
base64_in[0] = base64_in[1] = base64_in[2] = '\0';
for (i = 0; i < nData; i++)
base64_in[i] = *ucpData++;
base64_out[0] = ( base64_in[0] >> 2);
base64_out[1] = ((base64_in[0] & 0x03) << 4) + (base64_in[1] >> 4);
base64_out[2] = ((base64_in[1] & 0x0f) << 2) + (base64_in[2] >> 6);
if (n + 4 > bufsize)
return L2_ERR_MEM;
bufptr[n++] = base64_table[base64_out[0]];
bufptr[n++] = base64_table[base64_out[1]];
if (nData == 1)
bufptr[n++] = '=';
else
bufptr[n++] = base64_table[base64_out[2]];
bufptr[n++] = '=';
}
if (n >= bufsize)
return L2_ERR_MEM;
*buflen = n;
}
/* anything else is an unknown dumping method... */
else
return L2_ERR_ARG;
return L2_OK;
}
l2_result_t
l2_util_fmt_errno(
l2_context_t *ctx, const char id, const char *param,
char *bufptr, size_t bufsize, size_t *buflen, va_list *ap)
{
sprintf(bufptr, "(%d) %s", errno, strerror(errno));
*buflen = strlen(bufptr);
return L2_OK;
}