mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +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
|
use getgrouplist() when available instead of sequence of calls to
|
||||||
getgrent()
|
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:
|
docu:
|
||||||
libwrap always logs to syslog
|
libwrap always logs to syslog
|
||||||
|
|
||||||
|
|
32
compat.h
32
compat.h
|
@ -1,5 +1,5 @@
|
||||||
/* source: compat.h */
|
/* source: compat.h */
|
||||||
/* Copyright Gerhard Rieger 2001-2011 */
|
/* Copyright Gerhard Rieger */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __compat_h_included
|
#ifndef __compat_h_included
|
||||||
|
@ -622,34 +622,4 @@
|
||||||
extern const char *hstrerror(int);
|
extern const char *hstrerror(int);
|
||||||
#endif
|
#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) */
|
#endif /* !defined(__compat_h_included) */
|
||||||
|
|
|
@ -439,6 +439,9 @@
|
||||||
/* is uint64_t already defined? */
|
/* is uint64_t already defined? */
|
||||||
#undef HAVE_TYPE_UINT64
|
#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 */
|
/* Define if you have the printf "Z" modifier */
|
||||||
#undef HAVE_FORMAT_Z
|
#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
|
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_MSG_CHECKING(if printf has Z modifier)
|
||||||
AC_CACHE_VAL(ac_cv_have_z_modifier,
|
AC_CACHE_VAL(ac_cv_have_z_modifier,
|
||||||
[AC_TRY_RUN([
|
[AC_TRY_RUN([
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
main(){
|
int main(void){
|
||||||
char s[16];
|
char s[16];
|
||||||
sprintf(s,"%Zu",1);
|
sprintf(s,"%Zu",1);
|
||||||
exit(strcmp(s,"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;
|
int n;
|
||||||
|
|
||||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
#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);
|
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
|
||||||
*buff = '\0';
|
*buff = '\0';
|
||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
cp += n, blen -= n;
|
cp += n, blen -= n;
|
||||||
#endif
|
#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);
|
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
|
||||||
*buff = '\0';
|
*buff = '\0';
|
||||||
return buff;
|
return buff;
|
||||||
|
@ -204,13 +206,14 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
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);
|
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
|
||||||
*buff = '\0';
|
*buff = '\0';
|
||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
cp += n, blen -= n;
|
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",
|
"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)[0],
|
||||||
((unsigned char *)sau->soa.sa_data)[1],
|
((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)[10],
|
||||||
((unsigned char *)sau->soa.sa_data)[11],
|
((unsigned char *)sau->soa.sa_data)[11],
|
||||||
((unsigned char *)sau->soa.sa_data)[12],
|
((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");
|
Warn("sockaddr_info(): buffer too short");
|
||||||
*buff = '\0';
|
*buff = '\0';
|
||||||
return buff;
|
return buff;
|
||||||
|
@ -268,9 +272,9 @@ char *sockaddr_unix_info(const struct sockaddr_un *sa, socklen_t salen, char *bu
|
||||||
#if WITH_IP4
|
#if WITH_IP4
|
||||||
/* addr in host byte order! */
|
/* addr in host byte order! */
|
||||||
char *inet4addr_info(uint32_t addr, char *buff, size_t blen) {
|
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 >> 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");
|
Warn("inet4addr_info(): buffer too short");
|
||||||
buff[blen-1] = '\0';
|
buff[blen-1] = '\0';
|
||||||
}
|
}
|
||||||
|
@ -280,12 +284,12 @@ char *inet4addr_info(uint32_t addr, char *buff, size_t blen) {
|
||||||
|
|
||||||
#if WITH_IP4
|
#if WITH_IP4
|
||||||
char *sockaddr_inet4_info(const struct sockaddr_in *sa, char *buff, size_t blen) {
|
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)[0],
|
||||||
((unsigned char *)&sa->sin_addr.s_addr)[1],
|
((unsigned char *)&sa->sin_addr.s_addr)[1],
|
||||||
((unsigned char *)&sa->sin_addr.s_addr)[2],
|
((unsigned char *)&sa->sin_addr.s_addr)[2],
|
||||||
((unsigned char *)&sa->sin_addr.s_addr)[3],
|
((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");
|
Warn("sockaddr_inet4_info(): buffer too short");
|
||||||
buff[blen-1] = '\0';
|
buff[blen-1] = '\0';
|
||||||
}
|
}
|
||||||
|
@ -301,19 +305,19 @@ const char *inet_ntop(int pf, const void *binaddr,
|
||||||
switch (pf) {
|
switch (pf) {
|
||||||
case PF_INET:
|
case PF_INET:
|
||||||
if ((retlen =
|
if ((retlen =
|
||||||
snprintf(addrtext, textlen, "%u.%u.%u.%u",
|
xio_snprintf(addrtext, textlen, "%u.%u.%u.%u",
|
||||||
((unsigned char *)binaddr)[0],
|
((unsigned char *)binaddr)[0],
|
||||||
((unsigned char *)binaddr)[1],
|
((unsigned char *)binaddr)[1],
|
||||||
((unsigned char *)binaddr)[2],
|
((unsigned char *)binaddr)[2],
|
||||||
((unsigned char *)binaddr)[3]))
|
((unsigned char *)binaddr)[3]))
|
||||||
< 0) {
|
>= textlen) {
|
||||||
return NULL; /* errno is valid */
|
errno = ENOSPC; return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#if WITH_IP6
|
#if WITH_IP6
|
||||||
case PF_INET6:
|
case PF_INET6:
|
||||||
if ((retlen =
|
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)[0]),
|
||||||
ntohs(((uint16_t *)binaddr)[1]),
|
ntohs(((uint16_t *)binaddr)[1]),
|
||||||
ntohs(((uint16_t *)binaddr)[2]),
|
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)[6]),
|
||||||
ntohs(((uint16_t *)binaddr)[7])
|
ntohs(((uint16_t *)binaddr)[7])
|
||||||
))
|
))
|
||||||
< 0) {
|
>= textlen) {
|
||||||
return NULL; /* errno is valid */
|
errno = ENOSPC; return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif /* WITH_IP6 */
|
#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
|
/* convert the IP6 socket address to human readable form. buff should be at
|
||||||
least 50 chars long. output includes the port number */
|
least 50 chars long. output includes the port number */
|
||||||
char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen) {
|
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
|
#if HAVE_IP6_SOCKADDR==0
|
||||||
(sa->sin6_addr.s6_addr[0]<<8)+
|
(sa->sin6_addr.s6_addr[0]<<8)+
|
||||||
sa->sin6_addr.s6_addr[1],
|
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)[6]),
|
||||||
ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[7]),
|
ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[7]),
|
||||||
#endif
|
#endif
|
||||||
ntohs(sa->sin6_port)) < 0) {
|
ntohs(sa->sin6_port)) >= blen) {
|
||||||
Warn("sockaddr_inet6_info(): buffer too short");
|
Warn("sockaddr_inet6_info(): buffer too short");
|
||||||
buff[blen-1] = '\0';
|
|
||||||
}
|
}
|
||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
|
|
21
utils.c
21
utils.c
|
@ -1,5 +1,5 @@
|
||||||
/* source: utils.c */
|
/* source: utils.c */
|
||||||
/* Copyright Gerhard Rieger 2001-2009 */
|
/* Copyright Gerhard Rieger */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* useful additions to C library */
|
/* useful additions to C library */
|
||||||
|
@ -161,3 +161,22 @@ char *xiosubstr(char *scratch, const char *str, size_t from, size_t len) {
|
||||||
return scratch0;
|
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
|
extern
|
||||||
char *xiosubstr(char *scratch, const char *str, size_t from, size_t len);
|
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) */
|
#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
|
/* convert the IP6 socket address to human readable form. buff should be at
|
||||||
least 50 chars long. output includes the port number */
|
least 50 chars long. output includes the port number */
|
||||||
static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen) {
|
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
|
#if HAVE_IP6_SOCKADDR==0
|
||||||
(sa->s6_addr[0]<<8)+sa->s6_addr[1],
|
(sa->s6_addr[0]<<8)+sa->s6_addr[1],
|
||||||
(sa->s6_addr[2]<<8)+sa->s6_addr[3],
|
(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)[6]),
|
||||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[7])
|
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[7])
|
||||||
#endif
|
#endif
|
||||||
) < 0) {
|
) >= blen) {
|
||||||
Warn("sockaddr_inet6_info(): buffer too short");
|
Warn("sockaddr_inet6_info(): buffer too short");
|
||||||
buff[blen-1] = '\0';
|
buff[blen-1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue