about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlexander Barton <alex@barton.de>2014-01-04 23:57:05 +0100
committerAlexander Barton <alex@barton.de>2014-01-04 23:57:05 +0100
commit5d88030bd1a197041f84530a88c2590e6bb1bbb1 (patch)
treefa7f13b50eb15f3f54bbf08e4d1566de1b91784c /src
parent8872653ef6155bdaabd15c62ee67bd23d119305b (diff)
downloadngircd-5d88030bd1a197041f84530a88c2590e6bb1bbb1.tar.gz
ngircd-5d88030bd1a197041f84530a88c2590e6bb1bbb1.zip
Support non-standard vsnprintf() return code
C99 states that vsnprintf() "returns the number of characters that
would have been printed if the n were unlimited"; but according to the
Linux manual page "glibc until 2.0.6 would return -1 when the output
was truncated" -- so we have to handle both cases ...
Diffstat (limited to 'src')
-rw-r--r--src/ngircd/conn.c13
-rw-r--r--src/portab/portabtest.c25
2 files changed, 33 insertions, 5 deletions
diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c
index 3f447c61..fef568e4 100644
--- a/src/ngircd/conn.c
+++ b/src/ngircd/conn.c
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
  *
  * 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
@@ -984,6 +984,7 @@ va_dcl
 	size_t len;
 	bool ok;
 	va_list ap;
+	int r;
 
 	assert( Idx > NONE );
 	assert( Format != NULL );
@@ -993,7 +994,8 @@ va_dcl
 #else
 	va_start( ap );
 #endif
-	if (vsnprintf( buffer, COMMAND_LEN - 2, Format, ap ) >= COMMAND_LEN - 2 ) {
+	r = vsnprintf(buffer, COMMAND_LEN - 2, Format, ap);
+	if (r >= COMMAND_LEN - 2 || r == -1) {
 		/*
 		 * The string that should be written to the socket is longer
 		 * than the allowed size of COMMAND_LEN bytes (including both
@@ -1014,6 +1016,13 @@ va_dcl
 		 * an other server only routing the message!), so the only
 		 * option left is to shorten the string and to hope that the
 		 * result is still somewhat useful ...
+		 *
+		 * Note:
+		 * C99 states that vsnprintf() "returns the number of characters
+		 * that would have been printed if the n were unlimited"; but
+		 * according to the Linux manual page "glibc until 2.0.6 would
+		 * return -1 when the output was truncated" -- so we have to
+		 * handle both cases ...
 		 *                                                   -alex-
 		 */
 
diff --git a/src/portab/portabtest.c b/src/portab/portabtest.c
index 9e6bd228..b104739e 100644
--- a/src/portab/portabtest.c
+++ b/src/portab/portabtest.c
@@ -139,16 +139,35 @@ va_dcl
 {
 	char str[5];
 	va_list ap;
+	int r;
 
 #ifdef PROTOTYPES
 	va_start(ap, Format);
 #else
 	va_start(ap);
 #endif
-	if (vsnprintf(str, sizeof(str), Format, ap) != Len)
-		Panic("vsnprintf return code");
+	r = vsnprintf(str, sizeof(str), Format, ap);
 	va_end(ap);
-
+	if (r != Len) {
+		/* C99 states that vsnprintf() "returns the number of
+		 * characters that would have been printed if the n were
+		 * unlimited", but according to the Linux manual page "glibc
+		 * until 2.0.6 would return -1 when the output was truncated",
+		 * and other implementations (libUTIL on A/UX) even return the
+		 * number of characters processed ... so we only test our own
+		 * implementation and warn on errors otherwise :-/ */
+#ifdef HAVE_VSNPRINTF
+		fprintf(stderr,
+			"\n ** WARNING: The vsnprintf() function of this system isn't standard\n");
+		fprintf(stderr,
+			" ** conformant and returns a WRONG result: %d (should be %d)! The test\n",
+			r, Len);
+		fprintf(stderr,
+			" ** result has been ignored but may lead to errors during execution!\n\n");
+#else
+		Panic("vsnprintf return code");
+#endif
+	}
 	if (str[4] != '\0')
 		Panic("vsnprintf NULL byte");
 	if (strlen(str) != 4)