/* Copyright (C) 2008 Andreas Baumann 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 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "port/string.h" /** * strdup is not always part of the C library or they need insane flags to * be set which would enable too many non-standard things. */ #if !defined HAVE_STRDUP || defined TEST_STRDUP #include /* for malloc, NULL */ char *wolf_port_strdup( const char *s ) { char *d; d = (char *)malloc( strlen( s ) + 1 ); if( d == NULL ) return NULL; strcpy( d, s ); return d; } #endif /* !defined HAVE_STRDUP || defined TEST_STRDUP */ /** * strerror_r exists in various fassions (XSI and GNU flavour in glibc). We stick to * the API of POSIX.1 of course (XSI-compliant).. */ #if !defined HAVE_STRERROR_R || defined TEST_STRERROR_R #include "port/stdio.h" /* for snprintf */ #include "port/stdbool.h" /* for bool */ #include /* for size_t */ #include /* for errno */ #include "threads/mutex.h" /* for mutexes */ #ifdef HAVE_THREADS static bool mutex_initialized = false; static wolf_mutex_t mutex; #endif int wolf_port_strerror_r( int num, char *buf, size_t buflen ) { int safe_errno = errno; const char *msg; /* critical section as strerror is not thread-safe */ #ifdef HAVE_THREADS if( !mutex_initialized ) { wolf_mutex_init( &mutex ); mutex_initialized = true; } wolf_mutex_lock( &mutex ); #endif msg = strerror( num ); /* TODO: can we detect illegal error numbers? For sure on Linux NULL * is never returned and a strcmp with prefix "Unknown error" or similar * is not really acceptable. */ if( msg == NULL /* Solaris 8 */ || strncmp( msg, "Unknown error:", strlen( "Unknown error:" ) ) == 0 /* FreeBSD */ ) { /* Linux returns an empty string in this case, why? */ (void)snprintf( buf, buflen, "Unknown error %d", num ); errno = EINVAL; #ifdef HAVE_THREADS wolf_mutex_unlock( &mutex ); #endif return -1; } strncpy( buf, msg, buflen-1 ); errno = safe_errno; #ifdef HAVE_THREADS wolf_mutex_unlock( &mutex ); #endif return 0; } #endif /* !defined HAVE_STRERROR_R || defined TEST_STRERROR_R */ /** * str(n)casecmp is always around but on very old or strance C libraries. * We should only use it in 7-bit ASCII places like in the protocol. In * the Windows API they are called stri(n)cmp, so we have to map them * anyway. */ #if !defined HAVE_STRCASECMP || defined TEST_STRCASECMP #include /* for tolower */ int wolf_port_strcasecmp( const char *s1, const char *s2 ) { int c1, c2; do { c1 = tolower( (unsigned char)*s1 ); c2 = tolower( (unsigned char)*s2 ); s1++; s2++; } while( c1 == c2 && c1 != '\0' && c2 != '\0' ); return( c2 > c1 ? -1 : c1 > c2 ); } #endif /* !defined HAVE_STRCASECMP || defined TEST_STRCASECMP */ #if !defined HAVE_STRNCASECMP || defined TEST_STRNCASECMP #include /* for tolower */ int wolf_port_strncasecmp( const char *s1, const char *s2, size_t n ) { int c1, c2; if( n == 0 ) return 0; do { c1 = tolower( (unsigned char)*s1 ); c2 = tolower( (unsigned char)*s2 ); s1++; s2++; n--; } while( n > 0 && c1 == c2 && c1 != '\0' && c2 != '\0' ); return( c2 > c1 ? -1 : c1 > c2 ); } #endif /* !defined HAVE_STRNCASECMP || defined TEST_STRNCASECMP */ #if !defined HAVE_STRLCPY || defined TEST_STRLCPY size_t wolf_port_strlcpy( char *d, const char *s, size_t bufsize ) { size_t len; size_t ret; if( !d || !s || bufsize <= 0 ) return 0; len = strlen( s ); ret = len; if( len >= bufsize ) { len = bufsize-1; } memcpy( d, s, len ); d[len] = 0; return ret; } #endif /* !defined HAVE_STRLCPY || defined TEST_STRLCPY */ #if !defined HAVE_STRLCAT || defined TEST_STRLCAT size_t wolf_port_strlcat( char *d, const char *s, size_t bufsize ) { size_t len1; size_t len2; size_t ret; if( !d || !s || bufsize <= 0 ) return 0; len1 = strlen( d ); len2 = strlen( s ); ret = len1+len2; if( len1+len2 >= bufsize ) { len2 = bufsize - (len1+1); } if( (int)len2 >= 0 ) { memcpy( d+len1, s, len2 ); d[len1+len2] = 0; } return ret; } #endif /* !defined HAVE_STRLCAT || defined TEST_STRLCAT */