diff --git a/configure.in b/configure.in index c89043c4..24dfcae3 100644 --- a/configure.in +++ b/configure.in @@ -92,6 +92,17 @@ AC_CHECK_HEADER(sys/uio.h, AC_DEFINE(HAVE_SYS_UIO_H, 1, [Define if you have sys/ dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST +AC_MSG_CHECKING([how to copy va_list]) + AC_TRY_LINK([#include ], [va_list ap1, ap2; va_copy(ap1, ap2);], + AC_MSG_RESULT([va_copy]), + [ AH_TEMPLATE([va_copy], [define if va_copy is not available]) + AC_TRY_LINK([#include ], [va_list ap1, ap2; __va_copy(ap1, ap2);], + [ AC_DEFINE([va_copy], [__va_copy]) + AC_MSG_RESULT([__va_copy])], + [ AC_DEFINE([va_copy(dest,src)], [memcpy(&dest,&src,sizeof(va_list))]) + AC_MSG_RESULT([memcpy])] + ) + ]) dnl Check for types AC_CHECK_TYPE([socklen_t], int) diff --git a/src/net/sock.c b/src/net/sock.c index 30cc5c43..4354250d 100644 --- a/src/net/sock.c +++ b/src/net/sock.c @@ -57,6 +57,16 @@ #include "sock.h" #include "resolver.h" +#if 0 +#ifndef HAVE_VA_COPY + #ifdef HAVE___VA_COPY + #define va_copy(dest,src) __va_copy(dest, src) + #else + #define va_copy(dest,src) memcpy(&dest, &src, sizeof (va_list)) + #endif +#endif +#endif + /* sock_initialize ** ** initializes the socket library. you must call this @@ -312,25 +322,50 @@ int sock_write_string(sock_t sock, const char *buff) */ int sock_write(sock_t sock, const char *fmt, ...) { - char buff[1024]; + int rc; va_list ap; - va_start(ap, fmt); - vsnprintf(buff, 1024, fmt, ap); - va_end(ap); - - return sock_write_bytes(sock, buff, strlen(buff)); + va_start (ap, fmt); + rc = sock_write_fmt (sock, fmt, ap); + va_end (ap); + + return rc; } -int sock_write_fmt(sock_t sock, char *fmt, va_list ap) +int sock_write_fmt(sock_t sock, const char *fmt, va_list ap) { - char buff[1024]; + char buffer [1024], *buff = buffer; + int len; + int rc = SOCK_ERROR; + va_list ap_retry; - vsnprintf(buff, 1024, fmt, ap); + va_copy (ap_retry, ap); - return sock_write_bytes(sock, buff, strlen(buff)); + len = vsnprintf (buff, sizeof (buffer), fmt, ap); + + if (len > 0) + { + if ((size_t)len < sizeof (buffer)) /* common case */ + rc = sock_write_bytes(sock, buff, (size_t)len); + else + { + /* truncated */ + buff = malloc (++len); + if (buff) + { + len = vsnprintf (buff, len, fmt, ap_retry); + va_end (ap_retry); + if (len > 0) + rc = sock_write_bytes (sock, buff, len); + free (buff); + } + } + } + + return rc; } + int sock_read_bytes(sock_t sock, char *buff, const int len) { diff --git a/src/net/sock.h b/src/net/sock.h index eee7ef59..c58b12ce 100644 --- a/src/net/sock.h +++ b/src/net/sock.h @@ -88,7 +88,7 @@ int sock_connected (int sock, unsigned timeout); /* Socket write functions */ int sock_write_bytes(sock_t sock, const void *buff, const size_t len); int sock_write(sock_t sock, const char *fmt, ...); -int sock_write_fmt(sock_t sock, char *fmt, va_list ap); +int sock_write_fmt(sock_t sock, const char *fmt, va_list ap); int sock_write_string(sock_t sock, const char *buff); ssize_t sock_writev (int sock, const struct iovec *iov, const size_t count);