/*
* Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers.
* 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.
*
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
** Notice: this file is used by libmilter. Please try to avoid
** using libsm specific functions.
*/
/*
** XXX the type of the length parameter has been changed
** from size_t to ssize_t to avoid theoretical problems with negative
** numbers passed into these functions.
** The real solution to this problem is to make sure that this doesn't
** happen, but for now we'll use this workaround.
*/
/*
** SM_STRLCPY -- size bounded string copy
**
** This is a bounds-checking variant of strcpy.
** If size > 0, copy up to size-1 characters from the nul terminated
** string src to dst, nul terminating the result. If size == 0,
** the dst buffer is not modified.
** Additional note: this function has been "tuned" to run fast and tested
** as such (versus versions in some OS's libc).
**
** The result is strlen(src). You can detect truncation (not all
** of the characters in the source string were copied) using the
** following idiom:
**
** char *s, buf[BUFSIZ];
** ...
** if (sm_strlcpy(buf, s, sizeof(buf)) >= sizeof(buf))
** goto overflow;
**
** Parameters:
** dst -- destination buffer
** src -- source string
** size -- size of destination buffer
**
** Returns:
** strlen(src)
*/
register char *dst;
register const char *src;
{
register ssize_t i;
if (size-- <= 0)
continue;
dst[i] = '\0';
if (src[i] == '\0')
return i;
else
}
/*
** SM_STRLCAT -- size bounded string concatenation
**
** This is a bounds-checking variant of strcat.
** If strlen(dst) < size, then append at most size - strlen(dst) - 1
** characters from the source string to the destination string,
** nul terminating the result. Otherwise, dst is not modified.
**
** The result is the initial length of dst + the length of src.
** You can detect overflow (not all of the characters in the
** source string were copied) using the following idiom:
**
** char *s, buf[BUFSIZ];
** ...
** if (sm_strlcat(buf, s, sizeof(buf)) >= sizeof(buf))
** goto overflow;
**
** Parameters:
** dst -- nul-terminated destination string buffer
** src -- nul-terminated source string
** size -- size of destination buffer
**
** Returns:
** total length of the string tried to create
** (= initial length of dst + length of src)
*/
register char *dst;
register const char *src;
{
register ssize_t i, j, o;
if (size < o + 1)
size -= o + 1;
continue;
dst[j] = '\0';
if (src[i] == '\0')
return j;
else
}
/*
** SM_STRLCAT2 -- append two strings to dst obeying length and
** '\0' terminate it
**
** strlcat2 will append at most len - strlen(dst) - 1 chars.
** terminates with '\0' if len > 0
** dst = dst "+" src1 "+" src2
** use this instead of sm_strlcat(dst,src1); sm_strlcat(dst,src2);
** for better speed.
**
** Parameters:
** dst -- "destination" string.
** src1 -- "from" string 1.
** src2 -- "from" string 2.
** len -- max. length of "destination" string.
**
** Returns:
** total length of the string tried to create
** (= initial length of dst + length of src)
** if this is greater than len then an overflow would have
** occurred.
**
*/
register char *dst;
register const char *src1;
register const char *src2;
{
register ssize_t i, j, o;
/* current size of dst */
/* max. size is less than current? */
if (len < o + 1)
/* copy the first string; i: index in src1; j: index in dst */
continue;
/* src1: end reached? */
if (src1[i] != '\0')
{
/* no: terminate dst; there is space since i < len */
dst[j] = '\0';
}
len -= i; /* space left in dst */
/* copy the second string; i: index in src2; j: index in dst */
continue;
if (src2[i] == '\0')
return j;
else
}
/*
** SM_STRLCPYN -- concatenate n strings and assign the result to dst
** while obeying length and '\0' terminate it
**
** dst = src1 "+" src2 "+" ...
** use this instead of sm_snprintf() for string values
** and repeated sm_strlc*() calls for better speed.
**
** Parameters:
** dst -- "destination" string.
** len -- max. length of "destination" string.
** n -- number of strings
** strings...
**
** Returns:
** total length of the string tried to create
** (= initial length of dst + length of src)
** if this is greater than len then an overflow would have
** occurred.
*/
#ifdef __STDC__
#else /* __STDC__ */
register char *dst;
int n;
#endif /* __STDC__ */
{
register ssize_t i, j;
char *str;
SM_VA_START(ap, n);
if (len-- <= 0) /* This allows space for the terminating '\0' */
{
i = 0;
while (n-- > 0)
return i;
}
j = 0; /* index in dst */
/* loop through all source strings */
while (n-- > 0)
{
/* copy string; i: index in str; j: index in dst */
continue;
/* str: end reached? */
if (str[i] != '\0')
{
/* no: terminate dst; there is space since j < len */
dst[j] = '\0';
while (n-- > 0)
return j;
}
}
return j;
}
#if 0
/*
** SM_STRLAPP -- append string if it fits into buffer.
**
** If size > 0, copy up to size-1 characters from the nul terminated
** string src to dst, nul terminating the result. If size == 0,
** the dst buffer is not modified.
**
** This routine is useful for appending strings in a loop, e.g, instead of
** s = buf;
** for (ptr, ptr != NULL, ptr = next->ptr)
** {
** (void) sm_strlcpy(s, ptr->string, sizeof buf - (s - buf));
** s += strlen(s);
** }
** replace the loop body with:
** if (!sm_strlapp(*s, ptr->string, sizeof buf - (s - buf)))
** break;
** it's faster...
**
** XXX interface isn't completely clear (yet), hence this code is
** not available.
**
**
** Parameters:
** dst -- (pointer to) destination buffer
** src -- source string
** size -- size of destination buffer
**
** Returns:
** true if strlen(src) < size
**
** Side Effects:
** modifies dst if append succeeds (enough space).
*/
bool
register char **dst;
register const char *src;
{
register size_t i;
if (size-- <= 0)
return false;
continue;
(*dst)[i] = '\0';
if (src[i] == '\0')
{
*dst += i;
return true;
}
/* undo */
(*dst)[0] = '\0';
return false;
}
#endif /* 0 */