You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
933 lines
19 KiB
C
933 lines
19 KiB
C
/*
|
|
* binkleyforce -- unix FTN mailer project
|
|
*
|
|
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* $Id$
|
|
*/
|
|
|
|
#ifndef TEST
|
|
#include "includes.h"
|
|
#include "confread.h"
|
|
#include "logger.h"
|
|
#include "util.h"
|
|
#else
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
#define bool int
|
|
#define xmalloc malloc
|
|
#define xrealloc realloc
|
|
#define ASSERT
|
|
#endif
|
|
|
|
/*
|
|
* Maximum number of quoted-printable strings we will store together
|
|
*/
|
|
#define PRINTABLE_MAXITEMS 5
|
|
|
|
/*
|
|
* Cyclic buffer for quoted-printable strings
|
|
*/
|
|
static char *printable_storage[PRINTABLE_MAXITEMS];
|
|
|
|
/*
|
|
* Position of next entry to use in printable_storage[]
|
|
*/
|
|
static int printable_pos = -1;
|
|
|
|
|
|
/*****************************************************************************
|
|
* Allocate memory for the copy of a string pointed by src
|
|
*
|
|
* Arguments:
|
|
* src pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string (must be freed)
|
|
*/
|
|
char *xstrcpy(const char *src)
|
|
{
|
|
char *tmp;
|
|
|
|
if( !src )
|
|
return NULL;
|
|
|
|
tmp = xmalloc(strlen(src)+1);
|
|
strcpy(tmp, src);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Append string pointed by add to the string src, allocate memory for result
|
|
*
|
|
* Arguments:
|
|
* src pointer to the null-terminated string (will be freed)
|
|
* add this one will be appended to the src
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string (must be freed)
|
|
*/
|
|
char *xstrcat(char *src, const char *add)
|
|
{
|
|
char *tmp;
|
|
size_t size;
|
|
|
|
if( !add || *add == '\0' )
|
|
return src;
|
|
|
|
size = (src ? strlen(src) : 0) + strlen(add);
|
|
tmp = (char*)xmalloc(size+1);
|
|
|
|
if( src )
|
|
{
|
|
strcpy(tmp, src);
|
|
free(src);
|
|
} else
|
|
*tmp = '\0';
|
|
|
|
strcat(tmp, add);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Copy a string to the buffer. Checks for the destination buffer overflow and
|
|
* terminating '\0' character.
|
|
*
|
|
* Arguments:
|
|
* dst pointer to the destination buffer
|
|
* src string to copy from
|
|
* len destination buffer size
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string
|
|
*/
|
|
char *strnxcpy(char *dst, const char *src, size_t len)
|
|
{
|
|
ASSERT(src != NULL && dst != NULL && len >= 0);
|
|
|
|
dst[len - 1] = 0;
|
|
|
|
return strncpy(dst, src, len - 1);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Add one string to the end of another. Checks for destination buffer
|
|
* overflow and terminating '\0' character.
|
|
*
|
|
* Arguments:
|
|
* dst pointer to the destination buffer (append to the string
|
|
* stored in it)
|
|
* src append this string
|
|
* len destination buffer size
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string
|
|
*/
|
|
char *strnxcat(char *dst, const char *src, size_t len)
|
|
{
|
|
int pos;
|
|
|
|
ASSERT(src != NULL && dst != NULL && len >= 0);
|
|
|
|
pos = strlen(dst);
|
|
|
|
return strnxcpy(dst + pos, src, len - pos);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Get next substring from the string.
|
|
*
|
|
* Arguments:
|
|
* str pointer to a null-terminated string
|
|
* next points to the pointer where you want store address of
|
|
* the next substring for next calls
|
|
* delim delimiter characters, if NULL than the isspace() call used
|
|
* to check for the delimiter characters
|
|
* quoted ignore spaces in the quoted substrings
|
|
*
|
|
* Return value:
|
|
* Pointer to the new substring or NULL if no more available
|
|
*/
|
|
char *string_token(char *str, char **next, const char *delim, int quoted)
|
|
{
|
|
char *yield;
|
|
char *p;
|
|
|
|
ASSERT(next != NULL);
|
|
|
|
yield = str ? str : *next;
|
|
|
|
if( yield )
|
|
{
|
|
if( delim && *delim )
|
|
while( *yield && strchr(delim, *yield) ) yield++;
|
|
else
|
|
while( isspace(*yield) ) yield++;
|
|
|
|
if( *yield )
|
|
{
|
|
if( quoted && *yield == '"' )
|
|
{
|
|
p = ++yield;
|
|
while( *p && *p != '"' ) p++;
|
|
}
|
|
else
|
|
{
|
|
p = yield;
|
|
if( delim && *delim )
|
|
while( *p && !strchr(delim, *p) ) p++;
|
|
else
|
|
while( *p && !isspace(*p) ) p++;
|
|
}
|
|
if( *p )
|
|
{
|
|
*p = '\0';
|
|
*next = p+1;
|
|
} else
|
|
*next = NULL;
|
|
} else
|
|
yield = *next = NULL;
|
|
}
|
|
|
|
return yield;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Remove trailing CR and LF characters
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* Pointer to the string
|
|
*/
|
|
char *string_chomp(char *str)
|
|
{
|
|
char *p;
|
|
|
|
ASSERT(str != NULL);
|
|
|
|
if( str && *str )
|
|
{
|
|
p = str + strlen(str + 1);
|
|
if( *p == '\n' )
|
|
*p-- = '\0';
|
|
if( *p == '\r' && p >= str )
|
|
*p = '\0';
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Find the firtst occurance of substring into the string
|
|
*
|
|
* Arguments:
|
|
* substr pointer to the null-terminated substring
|
|
* string pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* Pointer to the first occurrence of the substring in the string,
|
|
* and NULL if substring is not found
|
|
*/
|
|
const char *string_casestr(const char *string, const char *substr)
|
|
{
|
|
size_t subln = strlen(substr);
|
|
size_t strln = strlen(string);
|
|
|
|
while( *string && strln >= subln )
|
|
{
|
|
if( !strncasecmp(substr, string, subln) )
|
|
return string;
|
|
|
|
++string;
|
|
--strln;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Find character in the string (It is like strchr(), but case insensitive)
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
* ch character you want to find
|
|
*
|
|
* Return value:
|
|
* Pointer to the first occurrence of the character in the string,
|
|
* and NULL if character is not found
|
|
*/
|
|
const char *string_casechr(const char *str, int ch)
|
|
{
|
|
ch = tolower(ch);
|
|
|
|
while( *str )
|
|
{
|
|
if( tolower(*str) == ch )
|
|
return str;
|
|
|
|
++str;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Convert string to the upper case
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* Pointer to the string
|
|
*/
|
|
char *string_toupper(char *str)
|
|
{
|
|
char *p;
|
|
|
|
ASSERT(str != NULL);
|
|
|
|
for( p = str; *p; p++ ) *p = toupper(*p);
|
|
|
|
return(str);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Convert string to the lower case
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* Pointer to the string
|
|
*/
|
|
char *string_tolower(char *str)
|
|
{
|
|
char *p;
|
|
|
|
ASSERT(str != NULL);
|
|
|
|
for( p = str; *p; p++ ) *p = tolower(*p);
|
|
|
|
return(str);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Check wheather string doesn't contain lower case characters
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* Return TRUE if string conforms our requirements, and FALSE if not
|
|
*/
|
|
bool string_isupper(const char *str)
|
|
{
|
|
const char *p;
|
|
|
|
ASSERT(str != NULL);
|
|
|
|
for( p = str; *p; p++ )
|
|
{
|
|
if( isalpha(*p) && islower(*p) ) break;
|
|
}
|
|
|
|
return (*p == '\0') ? TRUE : FALSE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Check wheather string doesn't contain upper case characters
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* Return TRUE if string conforms our requirements, and FALSE if not
|
|
*/
|
|
bool string_islower(const char *str)
|
|
{
|
|
const char *p;
|
|
|
|
ASSERT(str != NULL);
|
|
|
|
for( p = str; *p; p++ )
|
|
{
|
|
if( isalpha(*p) && isupper(*p) ) break;
|
|
}
|
|
|
|
return (*p == '\0') ? TRUE : FALSE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Remove spaces at the end of string
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* Pointer to the string
|
|
*/
|
|
char *string_trimright(char *str)
|
|
{
|
|
char *p;
|
|
|
|
ASSERT(str != NULL);
|
|
|
|
if( str && *str )
|
|
{
|
|
p = str + strlen(str+1);
|
|
while( p >= str && isspace(*p) ) *p-- = '\0';
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Remove spaces at the begining of string
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* pointer to the string
|
|
*/
|
|
char *string_trimleft(char *str)
|
|
{
|
|
char *p;
|
|
|
|
ASSERT(str != NULL);
|
|
|
|
if( str && *str )
|
|
{
|
|
p = str;
|
|
while( isspace(*p) ) p++;
|
|
if( p > str )
|
|
memmove(str, p, strlen(p)+1);
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Remove white spaces at the begining and at the end of string
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* pointer to the string
|
|
*/
|
|
char *string_trimboth(char *str)
|
|
{
|
|
char *p;
|
|
|
|
ASSERT(str != NULL);
|
|
|
|
if( str && *str )
|
|
{
|
|
/* Remove leading spaces */
|
|
p = str;
|
|
while( isspace(*p) ) p++;
|
|
if( p > str )
|
|
memmove(str, p, strlen(p)+1);
|
|
|
|
/* Remove trailing spaces */
|
|
p = str + strlen(str+1);
|
|
while( p >= str && isspace(*p) ) *p-- = '\0';
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Quote all unprintable characters in the buffer (e.g. "\xff\xfe")
|
|
*
|
|
* Arguments:
|
|
* buffer pointer to the buffer to process
|
|
* buflen buffer size
|
|
*
|
|
* Return value:
|
|
* Pointer to the quoted-printable string (must be freed)
|
|
*/
|
|
char *string_printable_buffer(const char *buffer, size_t buflen)
|
|
{
|
|
char *dest, *p;
|
|
const char *bp;
|
|
int nonprintcount = 0;
|
|
size_t pos = 0;
|
|
|
|
for( bp = buffer, pos = 0; pos < buflen; bp++, pos++ )
|
|
{
|
|
if( !isprint((unsigned char)*bp) )
|
|
nonprintcount++;
|
|
}
|
|
|
|
dest = xmalloc(buflen + nonprintcount * 4 + 1);
|
|
|
|
if( nonprintcount == 0 )
|
|
{
|
|
memcpy(dest, buffer, buflen);
|
|
dest[buflen] = '\0';
|
|
}
|
|
else
|
|
{
|
|
p = dest;
|
|
for( pos = 0; pos < buflen; buffer++, pos++ )
|
|
{
|
|
if( !isprint((unsigned char)*buffer) )
|
|
{
|
|
sprintf(p, "\\x%02x", (unsigned char)*buffer);
|
|
p += 4;
|
|
} else
|
|
*p++ = *buffer;
|
|
}
|
|
*p = '\0';
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Quote all unprintable characters in the string (e.g. "\xff\xfe")
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
*
|
|
* Return value:
|
|
* Pointer to the quoted-printable string. Memory allocated for the
|
|
* resulting string will be freed automatically. So don't use more
|
|
* than last PRINTABLE_MAXITEMS pointers returned by this function.
|
|
*/
|
|
const char *string_printable(const char *str)
|
|
{
|
|
char *p;
|
|
const char *q;
|
|
int nonprintcount = 0;
|
|
size_t pos = 0;
|
|
size_t len = 0;
|
|
|
|
if( printable_pos == -1 )
|
|
{
|
|
memset(printable_storage, '\0', sizeof(printable_storage));
|
|
printable_pos = 0;
|
|
}
|
|
|
|
if( str == NULL ) return "(null)";
|
|
|
|
len = strlen(str);
|
|
|
|
for( q = str, pos = 0; pos < len; q++, pos++ )
|
|
{
|
|
if( iscntrl((unsigned char)*q) || !isprint((unsigned char)*q) )
|
|
nonprintcount++;
|
|
}
|
|
|
|
if( !nonprintcount )
|
|
return str;
|
|
|
|
if( printable_pos >= PRINTABLE_MAXITEMS )
|
|
printable_pos = 0;
|
|
|
|
if( printable_storage[printable_pos] )
|
|
free(printable_storage[printable_pos]);
|
|
|
|
p = printable_storage[printable_pos] = xmalloc(len + nonprintcount * 4 + 1);
|
|
|
|
for( pos = 0; pos < len; str++, pos++ )
|
|
{
|
|
if( iscntrl((unsigned char)*str) || !isprint((unsigned char)*str) )
|
|
{
|
|
sprintf(p, "\\x%02x", (unsigned char)*str);
|
|
p += 4;
|
|
} else
|
|
*p++ = *str;
|
|
}
|
|
*p = '\0';
|
|
|
|
return printable_storage[printable_pos++];
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Replace all chracters 'oldchar' by the 'newchar'
|
|
*
|
|
* Arguments:
|
|
* str pointer to the null-terminated string
|
|
* oldchar old chracter
|
|
* newchar character to put istead of 'oldchar'
|
|
*
|
|
* Return value:
|
|
* Pointer to the string
|
|
*/
|
|
char *string_replchar(char *str, char oldchar, char newchar)
|
|
{
|
|
char *p = str;
|
|
|
|
while( *p )
|
|
{
|
|
if( *p == oldchar ) *p = newchar;
|
|
++p;
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Devide string on substrings and put pointers to them into the
|
|
* dest[] array.
|
|
*
|
|
* Arguments:
|
|
* dest destination array where we should put substrings
|
|
* items number of entries in dest[]
|
|
* str string to parse (will be destroyed)
|
|
* separator separator character
|
|
*
|
|
* Return value:
|
|
* Number of substrings in the dest[]
|
|
*/
|
|
int string_parse(char **dest, int items, char *str, int separator)
|
|
{
|
|
int count = 0;
|
|
char *p = str;
|
|
|
|
dest[count++] = str;
|
|
|
|
while( *p && count < items )
|
|
{
|
|
if( *((unsigned char *)p) == separator )
|
|
{
|
|
*p++ = '\0';
|
|
dest[count++] = p;
|
|
} else
|
|
++p;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Devide string on substrings separated by white-space characters and put
|
|
* pointers to them into the dest[] array. Also it will ignore spaces in
|
|
* quoted strings (quote characters will be removed)
|
|
*
|
|
* Arguments:
|
|
* dest destination array where we should put substrings
|
|
* items number of entries in dest[]
|
|
* str string to parse (will be destroyed)
|
|
*
|
|
* Return value:
|
|
* Number of substrings in the dest[]
|
|
*/
|
|
int string_parse_regular(char **dest, int items, char *str)
|
|
{
|
|
int count = 0;
|
|
char *p = str;
|
|
|
|
while( *p )
|
|
{
|
|
while( *p && isspace(*p) )
|
|
++p;
|
|
|
|
if( *((unsigned char *)p) == '"' && *++p )
|
|
{
|
|
dest[count++] = p;
|
|
while( *p && *((unsigned char *)p) != '"' ) p++;
|
|
}
|
|
else if( *p )
|
|
{
|
|
dest[count++] = p;
|
|
while( *p && !isspace(*p) ) p++;
|
|
}
|
|
|
|
if( *p && count < items )
|
|
*p++ = '\0';
|
|
else
|
|
break;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Replace all substrings 'find' by the 'repl' in the string 'str'
|
|
*
|
|
* Arguments:
|
|
* str null-terminated string to process (will be unchanged)
|
|
* find substring to find
|
|
* repl replace substring
|
|
*
|
|
* Return value:
|
|
* Pointer to the new string (must be freed)
|
|
*/
|
|
char *string_translate(const char *str, const char *find, const char *repl)
|
|
{
|
|
size_t sz_find = strlen(find);
|
|
size_t sz_repl = strlen(repl);
|
|
size_t sz_dest = strlen(str);
|
|
char *dest, *p;
|
|
|
|
p = dest = xstrcpy(str);
|
|
|
|
if( !sz_find ) return dest;
|
|
|
|
while( *p )
|
|
{
|
|
if( memcmp(p, find, sz_find) == 0 )
|
|
{
|
|
size_t offset = p - dest;
|
|
size_t newsize = sz_dest + (sz_repl - sz_find);
|
|
|
|
if( newsize > sz_dest )
|
|
dest = xrealloc(dest, newsize+1);
|
|
|
|
if( sz_repl > sz_find )
|
|
memmove(dest + offset + (sz_repl - sz_find), dest + offset, sz_dest - offset + 1);
|
|
else if( sz_repl < sz_find )
|
|
memmove(dest + offset, dest + offset + (sz_find - sz_repl), sz_dest - offset + 1);
|
|
|
|
memcpy(dest + offset, repl, sz_repl);
|
|
|
|
sz_dest = newsize;
|
|
p = dest + offset + sz_repl;
|
|
} else
|
|
++p;
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Convert size into human readable format (e.g. 100,256Kb or 20.7Mb)
|
|
*
|
|
* Arguments:
|
|
* buffer pointer to the buffer for resulting string
|
|
* size size in bytes that you want to print
|
|
*
|
|
* Return value:
|
|
* Pointer to the string
|
|
*/
|
|
char *string_humansize(char *buffer, size_t size)
|
|
{
|
|
if( size < 1024 )
|
|
sprintf(buffer, "%ldb", (long)size);
|
|
else if( size < 100*1024 )
|
|
sprintf(buffer, "%.1fK", ((double)size)/1024.0);
|
|
else if( size < 1000*1024 )
|
|
sprintf(buffer, "%ldK", (long)(size/1024));
|
|
else if( size < 100*1024*1024 )
|
|
sprintf(buffer, "%.1fM", ((double)size)/(1024.0*1024.0));
|
|
else if( size < 1000*1024*1024 )
|
|
sprintf(buffer, "%ldM", (long)(size/(1024*1024)));
|
|
else
|
|
sprintf(buffer, "%.1fG", ((double)size)/(1024.0*1024.0*1024.0));
|
|
|
|
return string_replchar(buffer, ',', '.');
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Interpret escape sequence (\xNN, \NNN, \r, \n, etc.)
|
|
*
|
|
* Arguments:
|
|
* pptr points a pointer to the first character after '\'
|
|
*
|
|
* Return value:
|
|
* Value of the escaped character
|
|
*/
|
|
int string_get_escape(char **pptr)
|
|
{
|
|
int ch = 0;
|
|
static const char *hexdigits = "0123456789abcdef";
|
|
char *p = *pptr;
|
|
|
|
if( *p == 'x' )
|
|
{
|
|
const char *q;
|
|
|
|
if( (q = string_casechr(hexdigits, *(++p))) )
|
|
{
|
|
ch = q - hexdigits;
|
|
if( (q = string_casechr(hexdigits, *(++p))) )
|
|
{
|
|
ch = ch * 16 + (q - hexdigits);
|
|
}
|
|
}
|
|
}
|
|
else if( *p == '0' || *p == '1' || *p == '2' || *p == '3' )
|
|
{
|
|
ch = *(p++) - '0';
|
|
if( isdigit(*p) && *p != '8' && *p != '9' )
|
|
{
|
|
ch = ch * 8 + (*(p++) - '0');
|
|
if( isdigit(*p) && *p != '8' && *p != '9' )
|
|
{
|
|
ch = ch * 8 + (*p - '0');
|
|
}
|
|
}
|
|
}
|
|
else switch(*p) {
|
|
case 'a':
|
|
ch = '\a'; break;
|
|
case 'b':
|
|
ch = '\b'; break;
|
|
case 'f':
|
|
ch = '\f'; break;
|
|
case 'n':
|
|
ch = '\n'; break;
|
|
case 'r':
|
|
ch = '\r'; break;
|
|
case 't':
|
|
ch = '\t'; break;
|
|
case '\\':
|
|
ch = '\\'; break;
|
|
default:
|
|
ch = *p;
|
|
}
|
|
|
|
*pptr = p + 1;
|
|
|
|
return (ch > 0) ? (ch & 0xff) : -1;
|
|
}
|
|
|
|
int string_dequote(char *dst, char *src)
|
|
{
|
|
char *d = dst;
|
|
char *s = src;
|
|
int ch;
|
|
|
|
while( *s )
|
|
{
|
|
if( s[0] == '\\' && s[1] )
|
|
{
|
|
++s;
|
|
ch = string_get_escape(&s);
|
|
if( ch != -1 )
|
|
*d++ = ch;
|
|
}
|
|
else
|
|
*d++ = *s++;
|
|
}
|
|
|
|
*d = '\0';
|
|
|
|
return 0;
|
|
}
|
|
|
|
char *string_concat(const char *str, ...)
|
|
{
|
|
va_list args;
|
|
size_t yield_len;
|
|
char *yield_ptr;
|
|
char *yield;
|
|
char *p;
|
|
|
|
/*
|
|
* Calculate total length of yielding string
|
|
*/
|
|
yield_len = strlen(str);
|
|
va_start(args, str);
|
|
while( (p = va_arg(args, char *)) )
|
|
yield_len += strlen(p);
|
|
va_end(args);
|
|
|
|
yield = xmalloc(yield_len + 1);
|
|
strncpy(yield, str, yield_len);
|
|
yield[yield_len] = '\0';
|
|
yield_ptr = yield + strlen(yield);
|
|
|
|
va_start(args, str);
|
|
while( (p = va_arg(args, char *)) )
|
|
{
|
|
strcpy(yield_ptr, p);
|
|
yield_ptr += strlen(p);
|
|
}
|
|
va_end(args);
|
|
|
|
return yield;
|
|
}
|
|
|
|
void string_bin_to_hex(char *string, const char *binptr, int binlen)
|
|
{
|
|
static const char *hexdigits = "0123456789abcdef";
|
|
int i;
|
|
|
|
for( i = 0; i < binlen; i++ )
|
|
{
|
|
*string++ = hexdigits[(*binptr >> 4) & 0x0f];
|
|
*string++ = hexdigits[(*binptr ) & 0x0f];
|
|
++binptr;
|
|
}
|
|
*string = '\0';
|
|
}
|
|
|
|
int string_hex_to_bin(char *binptr, const char *string)
|
|
{
|
|
static const char *hexdigits = "0123456789abcdef";
|
|
int len = (int)strlen(string);
|
|
int i, val;
|
|
const char *p;
|
|
char *dest = binptr;
|
|
|
|
for( i = 0; 2*i < len; i++ )
|
|
{
|
|
if( (p = string_casechr(hexdigits, *(string++))) )
|
|
{
|
|
val = (int)(p - hexdigits);
|
|
if( (p = string_casechr(hexdigits, *(string++))) )
|
|
{
|
|
val = val * 16 + (int)(p - hexdigits);
|
|
*dest++ = (unsigned char)(val & 0xff);
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
return (int)(dest - binptr);
|
|
}
|
|
|
|
bool string_is_empty(const char *string)
|
|
{
|
|
const char *p;
|
|
|
|
for( p = string; *p; p++ )
|
|
if( !isspace((int)(unsigned char)*p) )
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef TEST
|
|
int main(void)
|
|
{
|
|
char *hexstr = "0406ff2354124e6a9b2f6ed6ff00411287";
|
|
char binbuf[64];
|
|
int binlen;
|
|
char newhex[64];
|
|
|
|
/*
|
|
* string_hex_to_bin() and string_bin_to_hex()
|
|
*/
|
|
printf("*** Checking string_hex_to_bin() and string_bin_to_hex()\n");
|
|
printf("Original string : \"%s\"\n", hexstr);
|
|
binlen = string_hex_to_bin(binbuf, hexstr);
|
|
string_bin_to_hex(newhex, binbuf, binlen);
|
|
printf("Resulting string : \"%s\"\n", newhex);
|
|
if( strcmp(hexstr, newhex) )
|
|
printf("<<< ERROR!!! >>>\n");
|
|
|
|
return 0;
|
|
}
|
|
#endif /* TEST */
|
|
|