mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
Red Hat issue 1021948: snprintf API change
This commit is contained in:
parent
52e8a5ec2b
commit
cf39583b25
8 changed files with 74 additions and 53 deletions
5
CHANGES
5
CHANGES
|
@ -62,6 +62,11 @@ porting:
|
|||
use getgrouplist() when available instead of sequence of calls to
|
||||
getgrent()
|
||||
|
||||
Red Hat issue 1021948: snprintf API change;
|
||||
Implemented xio_snprintf() function as wrapper that tries to emulate C99
|
||||
behaviour on old glibc systems, and adapted all affected calls
|
||||
appropriately
|
||||
|
||||
docu:
|
||||
libwrap always logs to syslog
|
||||
|
||||
|
|
32
compat.h
32
compat.h
|
@ -1,5 +1,5 @@
|
|||
/* source: compat.h */
|
||||
/* Copyright Gerhard Rieger 2001-2011 */
|
||||
/* Copyright Gerhard Rieger */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __compat_h_included
|
||||
|
@ -622,34 +622,4 @@
|
|||
extern const char *hstrerror(int);
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* here are the declarations of compat.c */
|
||||
|
||||
#if !HAVE_SIGACTION
|
||||
struct sigaction {
|
||||
void (*sa_handler)(int);
|
||||
void (*sa_sigaction)(int, siginfo_t *, void *);
|
||||
sigset_t sa_mask;
|
||||
int sa_flags;
|
||||
} ;
|
||||
struct siginfo {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
pid_t si_pid;
|
||||
uid_t si_uid;
|
||||
int si_status;
|
||||
/*clock_t si_utime;*/
|
||||
/*clock_t si_stime;*/
|
||||
sigval_t si_value;
|
||||
int si_int;
|
||||
void *si_ptr;
|
||||
void *si_addr;
|
||||
/*int si_band;*/
|
||||
/*int si_fd;*/
|
||||
} ;
|
||||
extern int sigaction(int signum, const struct sigaction *act,
|
||||
struct sigaction *oldact);
|
||||
#endif /* !HAVE_SIGACTION */
|
||||
|
||||
#endif /* !defined(__compat_h_included) */
|
||||
|
|
|
@ -439,6 +439,9 @@
|
|||
/* is uint64_t already defined? */
|
||||
#undef HAVE_TYPE_UINT64
|
||||
|
||||
/* Define if snprintf() returns required len on truncation (C-99 conform) */
|
||||
#undef HAVE_C99_SNPRINTF
|
||||
|
||||
/* Define if you have the printf "Z" modifier */
|
||||
#undef HAVE_FORMAT_Z
|
||||
|
||||
|
|
20
configure.in
20
configure.in
|
@ -1284,11 +1284,29 @@ AC_CHECK_FUNC(SSLv2_server_method, AC_DEFINE(HAVE_SSLv2_server_method), AC_CHECK
|
|||
dnl Run time checks
|
||||
|
||||
|
||||
AC_MSG_CHECKING(if snprintf conforms to C99)
|
||||
AC_CACHE_VAL(ac_cv_have_c99_snprintf,
|
||||
[AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
int main(void){
|
||||
char s[2];
|
||||
exit(snprintf(s,2,"ab")!=2);
|
||||
}],
|
||||
[ac_cv_have_c99_snprintf=yes],
|
||||
[ac_cv_have_c99_snprintf=no],
|
||||
[ac_cv_have_c99_snprintf=no])])
|
||||
if test $ac_cv_have_c99_snprintf = yes; then
|
||||
AC_DEFINE(HAVE_C99_SNPRINTF)
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv_have_c99_snprintf)
|
||||
|
||||
|
||||
AC_MSG_CHECKING(if printf has Z modifier)
|
||||
AC_CACHE_VAL(ac_cv_have_z_modifier,
|
||||
[AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
main(){
|
||||
int main(void){
|
||||
char s[16];
|
||||
sprintf(s,"%Zu",1);
|
||||
exit(strcmp(s,"1"));
|
||||
|
|
39
sysutils.c
39
sysutils.c
|
@ -173,14 +173,16 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
|
|||
int n;
|
||||
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
if ((n = snprintf(cp, blen, "LEN=%d ", sau->soa.sa_len)) < 0) {
|
||||
n = xio_snprintf(cp, blen, "LEN=%d ", sau->soa.sa_len);
|
||||
if (n < 0 || n >= blen) {
|
||||
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
|
||||
*buff = '\0';
|
||||
return buff;
|
||||
}
|
||||
cp += n, blen -= n;
|
||||
#endif
|
||||
if ((n = snprintf(cp, blen, "AF=%d ", sau->soa.sa_family)) < 0) {
|
||||
n = xio_snprintf(cp, blen, "AF=%d ", sau->soa.sa_family);
|
||||
if (n < 0 || n >= blen) {
|
||||
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
|
||||
*buff = '\0';
|
||||
return buff;
|
||||
|
@ -204,13 +206,14 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
|
|||
break;
|
||||
#endif
|
||||
default:
|
||||
if ((n = snprintf(cp, blen, "AF=%d ", sa->sa_family)) < 0) {
|
||||
n = xio_snprintf(cp, blen, "AF=%d ", sa->sa_family);
|
||||
if (n < 0 || n >= blen) {
|
||||
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
|
||||
*buff = '\0';
|
||||
return buff;
|
||||
}
|
||||
cp += n, blen -= n;
|
||||
if ((snprintf(cp, blen,
|
||||
n = xio_snprintf(cp, blen,
|
||||
"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
((unsigned char *)sau->soa.sa_data)[0],
|
||||
((unsigned char *)sau->soa.sa_data)[1],
|
||||
|
@ -225,7 +228,8 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
|
|||
((unsigned char *)sau->soa.sa_data)[10],
|
||||
((unsigned char *)sau->soa.sa_data)[11],
|
||||
((unsigned char *)sau->soa.sa_data)[12],
|
||||
((unsigned char *)sau->soa.sa_data)[13])) < 0) {
|
||||
((unsigned char *)sau->soa.sa_data)[13]);
|
||||
if (n < 0 || n >= blen) {
|
||||
Warn("sockaddr_info(): buffer too short");
|
||||
*buff = '\0';
|
||||
return buff;
|
||||
|
@ -268,9 +272,9 @@ char *sockaddr_unix_info(const struct sockaddr_un *sa, socklen_t salen, char *bu
|
|||
#if WITH_IP4
|
||||
/* addr in host byte order! */
|
||||
char *inet4addr_info(uint32_t addr, char *buff, size_t blen) {
|
||||
if (snprintf(buff, blen, "%u.%u.%u.%u",
|
||||
if (xio_snprintf(buff, blen, "%u.%u.%u.%u",
|
||||
(unsigned int)(addr >> 24), (unsigned int)((addr >> 16) & 0xff),
|
||||
(unsigned int)((addr >> 8) & 0xff), (unsigned int)(addr & 0xff)) < 0) {
|
||||
(unsigned int)((addr >> 8) & 0xff), (unsigned int)(addr & 0xff)) >= blen) {
|
||||
Warn("inet4addr_info(): buffer too short");
|
||||
buff[blen-1] = '\0';
|
||||
}
|
||||
|
@ -280,12 +284,12 @@ char *inet4addr_info(uint32_t addr, char *buff, size_t blen) {
|
|||
|
||||
#if WITH_IP4
|
||||
char *sockaddr_inet4_info(const struct sockaddr_in *sa, char *buff, size_t blen) {
|
||||
if (snprintf(buff, blen, "%u.%u.%u.%u:%hu",
|
||||
if (xio_snprintf(buff, blen, "%u.%u.%u.%u:%hu",
|
||||
((unsigned char *)&sa->sin_addr.s_addr)[0],
|
||||
((unsigned char *)&sa->sin_addr.s_addr)[1],
|
||||
((unsigned char *)&sa->sin_addr.s_addr)[2],
|
||||
((unsigned char *)&sa->sin_addr.s_addr)[3],
|
||||
htons(sa->sin_port)) < 0) {
|
||||
htons(sa->sin_port)) >= blen) {
|
||||
Warn("sockaddr_inet4_info(): buffer too short");
|
||||
buff[blen-1] = '\0';
|
||||
}
|
||||
|
@ -301,19 +305,19 @@ const char *inet_ntop(int pf, const void *binaddr,
|
|||
switch (pf) {
|
||||
case PF_INET:
|
||||
if ((retlen =
|
||||
snprintf(addrtext, textlen, "%u.%u.%u.%u",
|
||||
xio_snprintf(addrtext, textlen, "%u.%u.%u.%u",
|
||||
((unsigned char *)binaddr)[0],
|
||||
((unsigned char *)binaddr)[1],
|
||||
((unsigned char *)binaddr)[2],
|
||||
((unsigned char *)binaddr)[3]))
|
||||
< 0) {
|
||||
return NULL; /* errno is valid */
|
||||
>= textlen) {
|
||||
errno = ENOSPC; return NULL;
|
||||
}
|
||||
break;
|
||||
#if WITH_IP6
|
||||
case PF_INET6:
|
||||
if ((retlen =
|
||||
snprintf(addrtext, textlen, "%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
xio_snprintf(addrtext, textlen, "%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
ntohs(((uint16_t *)binaddr)[0]),
|
||||
ntohs(((uint16_t *)binaddr)[1]),
|
||||
ntohs(((uint16_t *)binaddr)[2]),
|
||||
|
@ -323,8 +327,8 @@ const char *inet_ntop(int pf, const void *binaddr,
|
|||
ntohs(((uint16_t *)binaddr)[6]),
|
||||
ntohs(((uint16_t *)binaddr)[7])
|
||||
))
|
||||
< 0) {
|
||||
return NULL; /* errno is valid */
|
||||
>= textlen) {
|
||||
errno = ENOSPC; return NULL;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_IP6 */
|
||||
|
@ -341,7 +345,7 @@ const char *inet_ntop(int pf, const void *binaddr,
|
|||
/* convert the IP6 socket address to human readable form. buff should be at
|
||||
least 50 chars long. output includes the port number */
|
||||
char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen) {
|
||||
if (snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%hu",
|
||||
if (xio_snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%hu",
|
||||
#if HAVE_IP6_SOCKADDR==0
|
||||
(sa->sin6_addr.s6_addr[0]<<8)+
|
||||
sa->sin6_addr.s6_addr[1],
|
||||
|
@ -405,9 +409,8 @@ char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen
|
|||
ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[6]),
|
||||
ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[7]),
|
||||
#endif
|
||||
ntohs(sa->sin6_port)) < 0) {
|
||||
ntohs(sa->sin6_port)) >= blen) {
|
||||
Warn("sockaddr_inet6_info(): buffer too short");
|
||||
buff[blen-1] = '\0';
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
|
21
utils.c
21
utils.c
|
@ -1,5 +1,5 @@
|
|||
/* source: utils.c */
|
||||
/* Copyright Gerhard Rieger 2001-2009 */
|
||||
/* Copyright Gerhard Rieger */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* useful additions to C library */
|
||||
|
@ -161,3 +161,22 @@ char *xiosubstr(char *scratch, const char *str, size_t from, size_t len) {
|
|||
return scratch0;
|
||||
}
|
||||
|
||||
|
||||
/* since version 1.7.2.4 socat supports C-99 behaviour of snprintf but still
|
||||
can handle the old glibc case with -1 return on truncation.
|
||||
Do not rely on exact return value in case of truncation
|
||||
*/
|
||||
int xio_snprintf(char *str, size_t size, const char *format, ...) {
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start(ap, format);
|
||||
result = vsnprintf(str, size, format, ap);
|
||||
#if ! HAVE_C99_SNPRINTF
|
||||
if (result < 0) {
|
||||
result = size+63; /* indicate truncation with just some guess */
|
||||
}
|
||||
#endif /* !HAVE_C99_SNPRINTF */
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
|
|
3
utils.h
3
utils.h
|
@ -66,4 +66,7 @@ char *sanitize_string(const char *data, /* input data */
|
|||
extern
|
||||
char *xiosubstr(char *scratch, const char *str, size_t from, size_t len);
|
||||
|
||||
extern
|
||||
int xio_snprintf(char *str, size_t size, const char *format, ...);
|
||||
|
||||
#endif /* !defined(__utils_h_included) */
|
||||
|
|
|
@ -312,7 +312,7 @@ int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num,
|
|||
/* convert the IP6 socket address to human readable form. buff should be at
|
||||
least 50 chars long. output includes the port number */
|
||||
static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen) {
|
||||
if (snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
|
||||
if (xio_snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
|
||||
#if HAVE_IP6_SOCKADDR==0
|
||||
(sa->s6_addr[0]<<8)+sa->s6_addr[1],
|
||||
(sa->s6_addr[2]<<8)+sa->s6_addr[3],
|
||||
|
@ -368,7 +368,7 @@ static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen)
|
|||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[6]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[7])
|
||||
#endif
|
||||
) < 0) {
|
||||
) >= blen) {
|
||||
Warn("sockaddr_inet6_info(): buffer too short");
|
||||
buff[blen-1] = '\0';
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue