freebsd_amp_hwpstate/libsm/util.c

281 lines
5.0 KiB
C
Raw Normal View History

2007-04-09 01:38:51 +00:00
/*
2014-01-26 20:46:55 +00:00
* Copyright (c) 2006 Proofpoint, Inc. and its suppliers.
2007-04-09 01:38:51 +00:00
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
#include <sm/gen.h>
2014-05-22 03:45:17 +00:00
SM_RCSID("@(#)$Id: util.c,v 1.10 2013-11-22 20:51:44 ca Exp $")
2007-04-09 01:38:51 +00:00
#include <sm/setjmp.h>
#include <sm/conf.h>
#include <sm/assert.h>
#include <sm/heap.h>
#include <sm/string.h>
#include <sm/sendmail.h>
#include <ctype.h>
/*
** STR2PRT -- convert "unprintable" characters in a string to \oct
2023-01-15 19:15:36 +00:00
** (except for some special chars, see below)
2007-04-09 01:38:51 +00:00
**
** Parameters:
2023-01-15 19:15:36 +00:00
** s -- string to convert [A]
2007-04-09 01:38:51 +00:00
**
** Returns:
2023-01-15 19:15:36 +00:00
** converted string [S][U]
2007-04-09 01:38:51 +00:00
** This is a static local buffer, string must be copied
** before this function is called again!
*/
char *
str2prt(s)
char *s;
{
int l;
char c, *h;
bool ok;
static int len = 0;
static char *buf = NULL;
2023-01-15 19:15:36 +00:00
#if _FFR_LOGASIS >= 1
#define BADCHAR(ch) ((unsigned char)(ch) <= 31)
#else
#define BADCHAR(ch) (!(isascii(ch) && isprint(ch)))
#endif
2007-04-09 01:38:51 +00:00
if (s == NULL)
return NULL;
ok = true;
for (h = s, l = 1; *h != '\0'; h++, l++)
{
if (*h == '\\')
{
++l;
ok = false;
}
2023-01-15 19:15:36 +00:00
else if (BADCHAR(*h))
2007-04-09 01:38:51 +00:00
{
l += 3;
ok = false;
}
}
if (ok)
return s;
if (l > len)
{
char *nbuf = sm_pmalloc_x(l);
if (buf != NULL)
sm_free(buf);
len = l;
buf = nbuf;
}
for (h = buf; *s != '\0' && l > 0; s++, l--)
{
c = *s;
2023-01-15 19:15:36 +00:00
if (c != '\\' && !BADCHAR(c))
2007-04-09 01:38:51 +00:00
{
*h++ = c;
}
else
{
*h++ = '\\';
--l;
switch (c)
{
case '\\':
*h++ = '\\';
break;
case '\t':
*h++ = 't';
break;
case '\n':
*h++ = 'n';
break;
case '\r':
*h++ = 'r';
break;
default:
SM_ASSERT(l >= 2);
(void) sm_snprintf(h, l, "%03o",
(unsigned int)((unsigned char) c));
/*
2023-01-15 19:15:36 +00:00
** XXX since l is unsigned this may wrap
** around if the calculation is screwed up...
2007-04-09 01:38:51 +00:00
*/
l -= 2;
h += 3;
break;
}
}
}
*h = '\0';
buf[len - 1] = '\0';
return buf;
}
/*
** QUOTE_INTERNAL_CHARS -- do quoting of internal characters
**
** Necessary to make sure that we don't have metacharacters such
** as the internal versions of "$*" or "$&" in a string.
** The input and output pointers can be the same.
**
** Parameters:
2023-01-15 19:15:36 +00:00
** ibp -- a pointer to the string to translate [x]
** obp -- a pointer to an output buffer [i][m:A]
2007-04-09 01:38:51 +00:00
** bsp -- pointer to the length of the output buffer
**
** Returns:
** A possibly new bp (if the buffer needed to grow); if
** it is different, *bsp will updated to the size of
** the new buffer and the caller is responsible for
** freeing the memory.
*/
#define SM_MM_QUOTE(ch) (((ch) & 0377) == METAQUOTE || (((ch) & 0340) == 0200))
char *
2023-01-15 19:15:36 +00:00
#if SM_HEAP_CHECK > 2
quote_internal_chars_tagged
#else
quote_internal_chars
#endif
(ibp, obp, bsp, rpool
#if SM_HEAP_CHECK > 2
, tag, line, group
#endif
)
2007-04-09 01:38:51 +00:00
char *ibp;
char *obp;
int *bsp;
2023-01-15 19:15:36 +00:00
SM_RPOOL_T *rpool;
#if SM_HEAP_CHECK > 2
char *tag;
int line;
int group;
#else
# define tag "quote_internal_chars"
# define line 1
# define group 1
#endif
2007-04-09 01:38:51 +00:00
{
char *ip, *op;
int bufused, olen;
bool buffer_same, needs_quoting;
buffer_same = ibp == obp;
needs_quoting = false;
/* determine length of output string (starts at 1 for trailing '\0') */
for (ip = ibp, olen = 1; *ip != '\0'; ip++, olen++)
{
if (SM_MM_QUOTE(*ip))
{
olen++;
needs_quoting = true;
}
}
/* is the output buffer big enough? */
if (olen > *bsp)
{
2023-01-15 19:15:36 +00:00
obp = sm_rpool_malloc_tagged_x(rpool, olen, tag, line, group);
2007-04-09 01:38:51 +00:00
buffer_same = false;
*bsp = olen;
}
/*
** shortcut: no change needed?
** Note: we don't check this first as some bozo may use the same
** buffers but restrict the size of the output buffer to less
** than the length of the input buffer in which case we need to
** allocate a new buffer.
*/
if (!needs_quoting)
{
if (!buffer_same)
{
bufused = sm_strlcpy(obp, ibp, *bsp);
SM_ASSERT(bufused <= olen);
}
return obp;
}
if (buffer_same)
{
2023-01-15 19:15:36 +00:00
obp = sm_malloc_tagged_x(olen, tag, line + 1, group);
2007-04-09 01:38:51 +00:00
buffer_same = false;
*bsp = olen;
}
for (ip = ibp, op = obp, bufused = 0; *ip != '\0'; ip++)
{
if (SM_MM_QUOTE(*ip))
{
SM_ASSERT(bufused < olen);
op[bufused++] = METAQUOTE;
}
SM_ASSERT(bufused < olen);
op[bufused++] = *ip;
}
op[bufused] = '\0';
return obp;
}
2023-01-15 19:15:36 +00:00
#if SM_HEAP_CHECK <= 2
# undef tag
# undef line
# undef group
#endif
2007-04-09 01:38:51 +00:00
/*
** DEQUOTE_INTERNAL_CHARS -- undo the effect of quote_internal_chars
**
** Parameters:
2023-01-15 19:15:36 +00:00
** ibp -- a pointer to the string to be translated. [i]
** obp -- a pointer to the output buffer. [x]
** Can be the same as ibp.
2007-04-09 01:38:51 +00:00
** obs -- the size of the output buffer.
**
** Returns:
** number of character added to obp
*/
int
dequote_internal_chars(ibp, obp, obs)
char *ibp;
char *obp;
int obs;
{
char *ip, *op;
int len;
bool quoted;
quoted = false;
len = 0;
for (ip = ibp, op = obp; *ip != '\0'; ip++)
{
if ((*ip & 0377) == METAQUOTE && !quoted)
{
quoted = true;
continue;
}
if (op < &obp[obs - 1])
{
*op++ = *ip;
++len;
}
quoted = false;
}
*op = '\0';
return len;
}